概述
JDBC概述:JDBC为访问不同数据库提供统一接口,为使用者屏蔽细节问题。Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。
// 模拟代码
//JdbcInterface.java --Java规定的JDBC接口(方法)
public Interface JdbcInterface {public Object getConnect(); //连接public void crud(); //crud操作public void close(); //关闭连接
}//MySQLJdbcImpl.java --厂商的jdbc实现,数据库驱动
public class MysqlJdbcImpl implements JdbcInterface {@Overridepublic Object getConnect() { //连接System.out.println("得到mysql连接");return null;}public void crud(){ //crud操作System.out.println("完成mysql增删改查");}public void close(){ //关闭连接System.out.println("关闭mysql连接");}
}//TestJDBC.java --调用
public class TestJDBC {public static void main(String[] args) {JdbcInterface jdbcinterface = new MysqlJdbcImpl(); //创建接口引用jdbcinterface.getConnection() //通过接口调用实现类[多态 动态绑定机制:不同的对象,调用同意方法,返回不同的状态(不同类型的不同实现)]jdbcinterface.crud();jdbcinterface .close();}
}
JDBC快速入门
前置工作-添加驱动jar包:
1 拷贝到project_name/lib目录下
2 右击jar包 > Add as library… > OK
CREATE TABLE actor (id INT PRIMARY KEY AUTO_INCREMENT,`name` VARCHAR(32) NOT NULL DEFAULT '',sex CHAR(1) NOT NULL DEFAULT '女',bordate DATETIME,phone VARCHAR(12));
JDBC程序编写步骤
1 注册驱动-加载Driver类
2 获取连接-得到Connection
3 执行增删改查-发送SQL给mysql执行
4 释放资源-关闭相关连接
public class jdbc01 {public static void main(String[] args) throws SQLException {//1.注册驱动Driver driver = new Driver(); //创建driver对象//2.得到连接-mysql连接本质就是socket连接//(1) jdbc:mysql:// 规定好的表示协议,通过jdbc方式连接mysql//(2) localhost:3306 服务的ip(主机)和mysql监听端口//(3) hsp_db02 表示连接到mysql dbms的哪个数据库String url = "jdbc:mysql://localhost:3306/hsp_db02";//将用户名和密码放到Properties对象,key是user和password是规定好的,值根据实际情况填写Properties properties = new Properties();properties.setProperty("user", "root");//用户 密码//获取连接Connection connect = driver.connect(url, properties);//3.执行sqlString sql = "insert into actor values(null, '刘德华', '男', '1970-6-1', '110')"; //序号自增长用空Statement statement = connect.createStatement(); //用于执行静态SQL语句dml,并返回其生成的结果的对象;select语句使用executeQuery(sql)int rows = statement.executeUpdate(sql); //受影响的行数System.out.println(rows > 0 ? "成功": "失败"); //三元运算符//4.关闭连接statement.close();connect.close(); //不关闭会导致mysql连接太多,后续程序连接不上}
}
※JDBC API
JDBC API是一系列的接口,它统一和规范了应用程序与数据库的连接、执行SQL语句,并得到返回结果等各类操作,相关类和接口在java.sql与javax.sql包中。
PrepareStatement
DriverManager
Statement
ResultSet
获取数据库连接的最佳方式
public void connect05() throws IOException, ClassNotFoundException, SQLException {//使用配置文件,连接数据库更灵活 -- 最完善//通过Properties对象获取配置文件信息Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.properties"));String user = properties.getProperty("user");String password = properties.getProperty("password");String url = properties.getProperty("url");String driver = properties.getProperty("driver");//使用反射加载Driver类-动态加载,更加灵活,减少依赖性// 在加载driver类时完成注册(静态代码块)Class.forName(driver);Connection connection = DriverManager.getConnection(url, user, password);System.out.println(connection);}
ResuleSet 结果集
· 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
· ResuleSet对象保持一个光标指向其当前的数据行,最初光标位于第一行之前
· next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此使用while循环遍历结果
// 执行给定的SQL语句,该语句返回单个ResultSet对象ResultSet resultSet = statement.executeQuery(sql); //debug: resultSet = {JDBC42ResultSet@888} 是jdbc接口,实际是实现了该接口的类//5 使用while取出对象while (resultSet.next()) {int id = resultSet.getInt(1); //获取改行的第一列数据String name = resultSet.getString(2);String sex = resultSet.getString(3);Date date = resultSet.getDate(4);System.out.println(id + "\t" + name + "\t" + sex + "\t" + date);}//6 关闭连接resultSet.close();
SQl注入
Statement
Interface Statement:Statement对象 用于执行静态SQL语句并返回其生成结果的对象。
在连接建立后,需要对数据库进行访问,执行命令或是SQL语句,可以通过Statement
(存在SQL注入风险,实际开发中一般不使用)、PreparedStatement
(预处理)、CallableStatement
(存储过程)
SQL注入(SQL injection):是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库。
SELECT * FROM admin WHERE name = 'tom' AND pwd = '123';
SELECT * FROM admin WHERE name = '1' or ' AND pwd = 1' or'1' = '1'; # 用户名为 1' or 密码为 or '1' = '1 查询条件永远正确
要防范SQL注入,只要用PreparedStatement
(Statement扩展而来)取代Statement即可。
预处理
预处理查询
PreparedStatement
执行的SQL语句中的参数用问号(?)来表示,调用PreparedStatement
对象的.setXxx(param_index, param_value)
方法来设置这些参数,方法中的两个参数分别是SQL语句中的参数索引(从1开始)、参数值
调用excuteQuery()
,返回ResultSet对象
调用executeUpdate()
,执行更新,包括增、删、修改,返回受影响的行数。
优点(升级Statement):不再使用+拼接sql语句,减少语法错误;有效解决sql注入问题(通过控制访问的.setXxx()方法校验);减少编译次数,提高效率。
//3 得到PreparedStatement// 3.1 组织sql语句String sql = "select `name`, pwd from admin where `name` = ? and pwd = ?"; //sql语句的?相当于占位符// 3.2 接口 真正返回的对象是实现了该接口的类的实例PreparedStatement preparedStatement = connection.prepareStatement(sql);// 3.3 给sql参数赋值preparedStatement.setString(1, admin_name);preparedStatement.setString(2, admin_pwd);// 4 执行给定的SQL语句,该语句返回单个ResultSet对象ResultSet resultSet = preparedStatement.executeQuery(); // 绑定更新后的sql,不填参数sql,否则是包含?的if (resultSet.next()) { //如果查询到一条记录,则说明该管理员存在System.out.println("恭喜,登录成功");} else { // 控制住完成密码System.out.println("sorry,登录失败");}
预处理DML
// 3.1 组织sql语句
String sql1 = insert into admin values (?, ?)";
String sql2 = update admin set name = ? where pwd = ?";
String sql3 = delete from admin where name = ?";
...
// 4 执行给定的SQL语句,该语句返回单个ResultSet对象
int rows = preparedStatement.executeUpdate()
System.out.println(rows > 0 ? "执行成功" : "执行失败")