概述
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 {
@Override
public 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.执行sql
String 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 ? "执行成功" : "执行失败")