MySql - > 再谈数据连接 – > Driver - > Statement - > 工厂 – > 防止SQL注入
1: MySQL数据库
不收费 – > SUN - > Oracle
收费 – > MySql Classic
MySql EE
MySql ST
MariaDB - > 安全与mysql一样一样。
步1:下载mysql
步2:解压
步3:测试启动mysql数据库
用命令行,打开bin目录:
步4:不要关闭上面的界面,登录测试
默认的情况下,mysql有一个用户:root ,密码为 “”
也可以这样来登录:指定 -- user
也可以这样登录:指定服务器名称:
如果上面已经登录成功,则mysql就已经安装成功了.
步5:将mysql安装成服务
安装成功以后:
‘
可以在命令行启动mysql:
此时就可以关闭上面的界面。
再可以测试登录:
步6:为了在所有位置都可以执行mysql登录,可以将bin目录配置成path
2:配置mysql的性能
3:管理mysql的用户
Mysql数据库是用于管理其他的数据库的数据库 :
停止服务器,重新登录:
4:创建新的数据库
进入这个数据库,创建表:
5:远程登录mysql
以下是修改root用户,可以从 101这台机器登录:
以下是修改,root可以从所有机器登录:
卸载mysql
1:删除环境变量
2:删除服务
C:/bin/> mysqld –remove
3:删除文件
6:小结
1:解压mysql
2:启动测试 bin/> mysqld – - console
只要启动成功,就必须要停止以后再做后面的工作。CTRL+C
3:安装成成功 bin/> mysqld – - install
4:启动 net start mysql
5:配置环境变量 path
6:登录mysql 设置root的密码
C:/> mysql –uroot –p
7:设置mysql可以远程登录 同时修改root用户的密码
Host = %
…
8:停止 服务 c/> net stop mysql
C/> net start mysql
7:Java连接MySql
Java.sql.*/javax.sql.*
Dirver
Connection
Statement
ResultSet
DriverManager
步1:去下载mysql的驱动包
步2:将这个jar包放到项目中去,添加buildpath
步3:连接mysql数据库
public void test1() throws Exception {
// 1:加载驱动器
Class.forName("com.mysql.jdbc.Driver");
// 2:连接mysql数据库jdbc:mysql://localhost:3306/qlu =
// jdbc:mysql://127.0.0.1:3306/qlu = jdbc:mysql:///qlu
String url = "jdbc:mysql://192.168.0.234:3306/qlu?characterEncoding=UTF-8";
Connection con = DriverManager.getConnection(url, "root", "e234");
// System.err.println(con);//com.mysql.jdbc.JDBC4Connection@107ec20
// 3:创建数据操作对象
Statement st = con.createStatement();
// 4:查询
String sql = "select * from stud";
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
String id = rs.getString("id");
String name = rs.getString("name");
String age = rs.getString("age");
System.err.println(id + "," + name + "," + age);
}
rs.close();
st.close();
con.close();
}
8:注册驱动器
// 1:加载驱动器
Class.forName("com.mysql.jdbc.Driver"); - 》反射。
直接将驱动器注册给DriverManager的方式是:
static void | registerDriver(Driver driver) 向 DriverManager 注册给定驱动程序。 |
static Enumeration<Driver> | getDrivers() 返回你目前注册的所有驱动器。 |
// 实例化Oracle驱动器
OracleDriver driver = new OracleDriver();
// 注册
DriverManager.registerDriver(driver);
// 查询目前注册了几个驱动器
Enumeration<Driver> en = DriverManager.getDrivers();
while (en.hasMoreElements()) {
Driver d = en.nextElement();
System.err.println(d);
}
上面的注册驱动的最大的问题是:
1:严重依赖某个驱动。
2:重复注册。
Driver类的说明:
在加载某一 Driver 类时,它应该创建自己的实例并向 DriverManager 注册该实例。这意味着用户可以通过调用以下程序加载和注册一个驱动程序
Class.forName("foo.bah.Driver") – 将字节码载入内存
每一个驱动器,必须要自己在字节码载入内存时,向DriverManager注册自己:
静态代码块,何时执行:字节码载入内存时执行。
上面的代码,不依赖Oracle驱动器-依赖的是一个字符串:”oracle.jdbc.driver.OracleDriver” 只有在运行时才会依赖Oracle驱动器。
9:在不依赖的情况下,可以通过配置实现连接不同的数据库
通过配置的方式连接不同的的数据库,通过cxlass.forName(..)实现解偶。(反射的目的)
配置方式:
Xml是配置文件。
资源文件来配置 - *.properties
步1:添加一个jdbc.properties
步2:开发一个工具类(工厂方法静态方法),读取资源文件,创建一个唯一的connection
package cn.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
public class ConnUtils {
// 1:声明一个唯一的连接
private static Connection con;
// 2:在静态的代码块中只连接数据库一次
static {
try {
// 声明资源文件类
Properties prop = new Properties();
// 加载配置的文件 bin/jdbc.prop[erties
prop.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));
// 获取里面的配置
String driver = prop.getProperty("qdq");
String url = prop.getProperty("url");
String name = prop.getProperty("name");
String pwd = prop.getProperty("pwd");
// 连接
Class.forName(driver);
con = DriverManager.getConnection(url, name, pwd);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 提供一个工厂方法,返回ocn
public static Connection getCon() {
return con;
}
}
10:小结
1:为什么要使用Class.forName(‘。。。”)去加载驱动 – 》 解偶。(可以通过配置的方式,实现连接不同的数据库)
2:不会重复的注册。
3:建议开发一个工厂类,维护一个唯一的连接。重用同一个连接。
目前:
1:如何注册驱动。
2:开发工厂类连接数据库。
11:Statement对象
Driver – 驱动器,只注册一次。
Connection – 连接对象 – 》 只有一个连接,就可以通过它向数据库发送SQL语句。
Satement 每次操作SQL都可以创建一个新。
ResutlSet 每次查询都返回一个结果集。
Statement的一些方法:
java.sql 接口 Statement
ResultSet | executeQuery(String sql) 固定的只接收select 语句。返回一个查询的结果集。 |
(略)
int | executeUpdate(String sql) 执行INSERT、UPDATE 或 DELETE 语或是DDL 语句。 (略)
|
重载:
int | executeUpdate(String sql, int autoGeneratedKeys) 第二个参数,是指是否返回数据库自动的创建的主键。
|
int | executeUpdate(String sql, int[] columnIndexes) 指定哪一个列返回生成的值
public void test1() throws Exception { Connection con = ConnUtils.getCon(); Statement st = con.createStatement(); String sql = "insert into person(id,name,age) values(sys_guid(),'张三3',99)"; int rows = st.executeUpdate(sql, new int[] { 1, 2 });// 可以返回DB生成的值 // 获取生成的值 ResultSet rs = st.getGeneratedKeys(); // 因为只有一个值,所以不用while,用if if (rs.next()) { String id = rs.getString(1);// 只有一列 String name = rs.getString(2); System.err.println("生成的主键 是:" + id+","+name); }
// //自动生成的id是:
st.close(); con.close(); }
|
int | executeUpdate(String sql, String[] columnNames) 执行给定的 SQL 语句,并通知驱动程序在给定数组中指示的自动生成的键应该可用于获取。
public void test1() throws Exception { Connection con = ConnUtils.getCon(); Statement st = con.createStatement(); String sql = "insert into person(id,name,age) values(sys_guid(),'张三33',99)"; int rows = st.executeUpdate(sql,new String[]{ "id","name"});// 可以返回DB生成的值 // 获取生成的值 ResultSet rs = st.getGeneratedKeys(); // 因为只有一个值,所以不用while,用if if (rs.next()) { String id = rs.getString(1);// 只有一列 String name = rs.getString(2); System.err.println("生成的主键 是:" + id+","+name); }
// //自动生成的id是:
st.close(); con.close(); } |
创建一个有主键的表:
写入主键的方式:
1:Java代码生成主键 – Java代码可以获取主键的值
public void test1() throws Exception {
Connection con = ConnUtils.getCon();
Statement st = con.createStatement();
// 用Java代码来生成主键,可以使用java.util.UUID类。
String id = UUID.randomUUID().toString().replace("-","");
String sql = "insert into person(id,name,age) values('"+id+"','Jack',44)";
st.executeUpdate(sql);
st.close();
con.close();
}
2:数据库生成主键
(sys_guid(),sequence )
@Test
public void test1() throws Exception {
Connection con = ConnUtils.getCon();
Statement st = con.createStatement();
String sql = "insert into person(id,name,age) values(sys_guid(),'张三1',99)";
int rows = st.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);// 可以返回DB生成的值
// 获取生成的值
ResultSet rs = st.getGeneratedKeys();
// 因为只有一个值,所以不用while,用if
if (rs.next()) {
String id = rs.getString(1);// 只有一列
System.err.println("生成的主键 是:" + id);
}
// //自动生成的id是:
st.close();
con.close();
}
默认的在oracle里面返回是rowid
boolean | execute(String sql) 执行给定的 SQL 语句,该语句可能返回多个结果。 |
boolean | execute(String sql, int autoGeneratedKeys) 执行给定的 SQL 语句(该语句可能返回多个结果),并通知驱动程序所有自动生成的键都应该可用于获取。 |
boolean | execute(String sql, int[] columnIndexes) 执行给定的 SQL 语句(该语句可能返回多个结果),并通知驱动程序在给定数组中指示的自动生成的键应该可用于获取。 |
boolean | execute(String sql, String[] columnNames) 执行给定的 SQL 语句(该语句可能返回多个结果),并通知驱动程序在给定数组中指示的自动生成的键应该可用于获取。 |
返回:
如果第一个结果为 ResultSet 对象,则返回 true;如果其为更新计数或者不存在任何结果,则返回 false
如果执行是select 则返回 true,否则返回false。
Connection con = ConnUtils.getCon();
Statement st = con.createStatement();
String sql = "insert into person(id,name,age) values(sys_guid(),'张三199',99)";
boolean boo = st.execute(sql);// 可以返回DB生成的值
System.err.println(boo);//false
@Test
public void test1() throws Exception {
Connection con = ConnUtils.getCon();
Statement st = con.createStatement();
String sql = "select * from person";
boolean boo = st.execute(sql);// 可以返回DB生成的值
System.err.println(boo);// true
if (boo) {
ResultSet rs = st.getResultSet();
while (rs.next()) {
String name = rs.getString("name");
System.err.println(name);
}
}
}
批量处理
void | addBatch(String sql) 将给定的 SQL 命令添加到此 Statement 对象的当前命令列表中。 |
int[] | executeBatch() 将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。 返回的int[]长度是指执行了多少SQL语句 int.length=sql语句的个数。 int[1,2,32,4,45] 里面每一个元素的值是影响了几行数据。
|
@Test
public void test1() throws Exception {
Connection con = ConnUtils.getCon();
Statement st = con.createStatement();
for (int i = 0; i < 10; i++) {
String sql = "insert into person(id,name,age) values(sys_guid(),'Jack" + i + "',33)";
st.addBatch(sql);
}
st.addBatch("update person set age=age+1");
//执行
int[] rows = st.executeBatch();
System.err.println(rows.length);//11
System.err.println(Arrays.toString(rows));//影响几:[1,1,1,1,1,1,1,1,1,1,20] = 30
st.close();
con.close();
}
12:SQL注入
@Test
public void testLogin() throws Exception {
Connection con = ConnUtils.getCon();
Statement st = con.createStatement();
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
String pwd = sc.nextLine();
String sql ="select * from users where name='"+name+"' and pwd='"+pwd+"'";
System.err.println(sql);
ResultSet rs = st.executeQuery(sql);
if(rs.next()){
System.err.println("登录成功");
}else{
System.err.println("用户名或是密码错误..");
}
st.close();
con.close();
}
要是接收用户输入的,就不能使用字符串连接。
使用PreparedStament查询?
@Test
public void testLogin2() throws Exception {
Connection con = ConnUtils.getCon();
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
String pwd = sc.nextLine();
String sql ="select * from users where name=? and pwd=?";
PreparedStatement pst = con.prepareStatement(sql);
pst.setString(1, name);
pst.setString(2, pwd);
System.err.println(sql);
ResultSet rs = pst.executeQuery();
if(rs.next()){
System.err.println("登录成功");
}else{
System.err.println("用户名或是密码错误..");
}
pst.close();
con.close();
}
1:开发连接数据库的工具类。
2:将Demo1.java中的所有Statement都修改成Pst对象。
package cn.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
import org.junit.Test;
import cn.utils.ConnUtils;
public class Demo01 {
@Test
public void testQuery() throws Exception {
Statement st = ConnUtils.getCon().createStatement();
System.err.println("数据操作对象:" + st);// oracle.jdbc.driver.OracleStatementWrapper@3884b2
// 4:执行SQL语句
String sql = "select * from stud";
ResultSet rs = st.executeQuery(sql);
// 遍历结果集
while (rs.next()) {
// 获取里面的数据
int id = rs.getInt(1);//数据库的查询,下标从1开始1=id
String name = rs.getString(2);
System.err.println(id + "," + name);
}
rs.close();
st.close();
// 最后使用完成,就关闭连接
}
@Test
public void testInsert() throws Exception {
Statement st = ConnUtils.getCon().createStatement();
Scanner sc = new Scanner(System.in);
String id = sc.nextLine();
String name = sc.nextLine();
// 声明Sql insert
String sql = "insert into stud(id,name) values(" + id + ",'" + name + "')";
// 写入数据
int rows = st.executeUpdate(sql);
System.err.println("影响行数 :" + rows);
st.close();
}
@Test
public void testDelete() throws Exception {
Statement st = ConnUtils.getCon().createStatement();
Scanner sc = new Scanner(System.in);
String id = sc.nextLine();
// 声明Sql insert
String sql = "delete from stud where id=" + id;
// 写入数据
int rows = st.executeUpdate(sql);
System.err.println("影响行数 :" + rows);
st.close();
}
@Test
public void testUpdate() throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@192.168.56.101:1521/xe";
Connection con = DriverManager.getConnection(url, "scott", "tiger");
Statement st = con.createStatement();
Scanner sc = new Scanner(System.in);
String id = sc.nextLine();
String name = sc.nextLine();
// 声明Sql insert
String sql = "update stud set name='" + name + "' where id=" + id;
// 写入数据
int rows = st.executeUpdate(sql);
System.err.println("影响行数 :" + rows);
st.close();
con.close();
}
public static void main(String[] args) throws Exception {
new Demo01();
}
public Demo01() throws Exception {
Scanner sc = new Scanner(System.in);
one: while (true) {
String op = sc.nextLine();
switch (op) {
case "query":
testQuery();
break;
case "delete":
testDelete();
break;
case "update":
testUpdate();
break;
case "insert":
testInsert();
break;
case "exit":
break one;
default:
break;
}
}
}
}