Java Database Connectivity ,Java连接数据库的技术,可以理解为一组规范(接口),实际上不是接口。
JDBC驱动可以理解为JDBC的实现类,实际上不是实现类。
JDBC核心API
1. DriverManager类 管理不同的驱动
2. Connection 接口 应用和数据库的连接
3. Statement 接口 用于执行sql语句
4. ResultSet 接口 保存查询的结果
原生JDBC实现数据库操作
查询
public class JDBCTest1 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.注册驱动,利用反射实现
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql:///cp", "root", "123");
//3.获取sql编译器,书写sql语句
Statement st = conn.createStatement();
String sql = "select * from user";
//4.执行sql语句,获取结果集
ResultSet rs = st.executeQuery(sql);
//5.解析结果集
while (rs.next()) {
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
String name = rs.getString("name");
String sex = rs.getString("sex");
String hobby = rs.getString("hobby");
String sdesc = rs.getString("sdesc");
System.out.println(id+": "+username);
}
//6.关闭流资源,先开后关
rs.close();
st.close();
conn.close();
}
}
增删改
public class JDBCTest2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.注册驱动,利用反射实现
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql:///cp", "root", "123");
//3.获取sql编译器,书写sql语句
Statement st = conn.createStatement();
String sql = "insert into user values(null,'admin','123','亦凡','男人','打飞机','猥琐')";
//4.执行sql语句,返回的是受影响的行数
int row = st.executeUpdate(sql);
System.out.println(row > 0?"新增成功":"新增失败");
//5.关闭流资源,先开后关
st.close();
conn.close();
}
}
常用的开源连接池
1. DBCP
是Apache提供的数据库连接池,速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持
2. C3P0
是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以
ComboPooledDataSource dataSource = new ComboPooledDataSource();
3.Druid
是阿里提供的数据库连接池,据说是集DBCP 、C3P0 优点于一身的g高性能的数据库连接池
4.HikariCp
SpringBoot2.0+默认的连接池,性能强、速度快,遥遥领先其他连接池(建议使用)
Springboot 2.0选择HikariCP作为默认数据库连接池的五大理由
https://blog.didispace.com/Springboot-2-0-HikariCP-default-reason/
PreparedStatement解决SQL注入问题PreparedStatement对象会将SQL语句进行预编译,通过?占位符的方式进行SQL语句参数的拼接,这样就避免将字符中的内容当成SQL关键字参与编译执行,从而解决SQL注入问题。
PreparedSatement的执行原理与区别
1、Statement 对象每执行一条SQL语句都会先将这条SQL语句发送给数据库编译,数据库再执行。
如果有1万条类似的SQL语句,数据库需要编译1万次,执行1万次,显然效率就低了
2、prepareStatement() 会先将SQL语句发送给数据库预编译。 PreparedStatement 会引用着预编译后的结果。
如果有1万条类似的插入数据的语句。数据库只需要预编译一次,传入1万次不同的参数并执行。减少了SQL语句的编译次数,提高了执行效率。
PreparedStatement常见方法
setInt(int index,int value)
为?占位符,赋予int值
int index: 第几个?占位符
int value: 赋值的是int值
setString(int index,String value) 为?占位符,赋予String值
PreparedStatement预编译对象实现JDBC
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class PreparedStatementTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql:///cp", "root", "123");
//3.书写Sql语句
String sql = "insert into user values(null,?,?,?,?,?,?)";
//4.获取预编译对象,参数传入sql语句
PreparedStatement ps = conn.prepareStatement(sql);
//5.设置参数
ps.setString(1,"kris");
ps.setString(2,"123");
ps.setString(3,"吴亦凡");
ps.setString(4,"妖人");
ps.setString(5,"骗炮");
ps.setString(6,"炮王");
//6.执行sql语句
int row = ps.executeUpdate();
System.out.println(row>0?"新增成功":"新增失败");
//7.关闭资源
ps.close();
conn.close();
}
}
事务的特性(ACID):
(1)原子性(Atomicity):多条语句、作为一个整体单元、要么里面所有语句都成功、要么里面的语句都失败。
(2)一致性(Consistency):事务执行前和执行后状态一致、要么都是成功状态、要么都是失败状态
(3)隔离性(Isolation):多个事务、在并行的情况下,事务和事务之间相互隔离互不影响。
(4)持久性(Durability):事务一旦提交数据将永久的保存、不受其他因素所干扰
DBUtils
DBUtils中的常用类
QueryRunner
QueryRunner():无参构造方法。如果使用该方法构造,增删改查方法就需要自己搞数据库连接,有事务。
QueryRunner(DataSource ds):带有数据源。增删改查就不用指定数据库连接,会自动从数据源获取连接,无事务。
增删改查方法
增删改方法:
int update(Connection conn,String sql,Object...params):返回影响到的行数。对应无参构造。
int update(String sql,Object...params):返回影响到的行数。对应有数据源参数的构造。
查询方法:
<T> T query(Connection conn,String sql,ResultSetHandler rsh,Object...params):执行查询,对应无参构造。
<T> T query(String sql,ResultSetHandler rsh,Object...params):执行查询,对应有数据源参数的构造。
ResultSetHandler
ResultSetHandler:结果集处理器,是一个接口。
实现类:
1. BeanHandler:封装一条记录
2. BeanListHandler:封装多条记录
3. ScalerHandler:封装单行单列数据。
DBUtils整合C3P0实现JDBC操作
public class DBUtil {
public static void main(String[] args) throws SQLException {
ComboPooledDataSource ds = new ComboPooledDataSource();
QueryRunner qr = new QueryRunner(ds);
String sql = "select * from user where id = ?";
Object[] params = {1};
User user = qr.query(sql, new BeanHandler<User>(User.class), params);
System.out.println(user.getName()+": "+user.getSdesc());
}
}