什么叫JDBC
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());
    }
}