1. JDBC

  • 导入mysql-connector-java.jar包

  • 注册驱动

      1. Class.forName("com.mysql.jdbc.Driver");
  • 建立连接

      1. Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql", "root", "123456");
  • 获取对象

      1. Statement stat = con.createStatement();
  • 执行sql语句

      1. String sql ="select * from help_relation";
      2. ResultSet result = stat.executeQuery(sql);
  • 处理结果

      1. while (result.next()){
      2. System.out.println(result.getInt("help_topic_id")+"\t"+ result.getString("help_keyword_id"));
      3. }
  • 关闭连接

      1. con.close();
      2. stat.close();

2. DriverManager 连接

DriverManager驱动管理对象

  • 注册驱动 registerDriver(Driver river) 注册给定的驱动 在上面注册中我们使用class.forname使用了一下Driver这个类,默认被使用就注册驱动 必须是mysql5之后才可以省略这个注册
  • 获取数据连接 getConnection(url , user , password) url为jdbc:mysql://ip:端口/库名

3. Connection 连接对象

Connection数据库连接对象

  • 获取普通执行者对象 createStatement()
  • 获取预编译执行者对象 prepareStatement(String sql)
  • 开启事务 setAutoCommit(boolean autoCommit); 参数为false 则开启事务
  • 提交事务 commit()
  • 回滚事务 rollback()
  • 释放资源 close();

4. Statement 执行语句

Statement执行sql语句的对象

  • 增删改 executeUpdate(String sql) 返回一个int 影响的行数 可以执行 insert、update、delete语句
  • 查询 executeQuery(String sql) 返回值resultset对象 封装查询的结果 可以执行select语句
  • 释放资源 close()

5. ResultSet 结果

ResultSet结果集对象

  • 判断结果是否还有数据 next() 有数据返回ture,并索引向下移动一行
  • get数据类型(“列名”) 返回指定列的指定数据类型结果 如getInt() getString()
  • 释放资源 close()

6. 工具类

在src下创建config.properties 文件

  1. driverClass=com.mysql.jdbc.Driver
  2. url=jdbc:mysql://127.0.0.1:3306/mysql
  3. username=root
  4. password=123456
  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.sql.*;
  4. import java.util.Properties;
  5. public class JDBCUtils {
  6. private JDBCUtils() {
  7. }
  8. //2.声明需要的配置变量
  9. private static String driverClass;
  10. private static String url;
  11. private static String usename;
  12. private static String password;
  13. private static Connection con;
  14. //3.提供静态代码块 读取配置文件为变量赋值
  15. static {
  16. try {
  17. InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");
  18. Properties prop = new Properties();
  19. prop.load(is);
  20. driverClass = prop.getProperty("driverClass");
  21. url = prop.getProperty("url");
  22. usename = prop.getProperty("usename");
  23. password = prop.getProperty("password");
  24. //注册驱动
  25. Class.forName(driverClass);
  26. } catch (Exception e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. public static Connection getConnection() {
  31. try {
  32. con = DriverManager.getConnection(url, usename, password);
  33. } catch (SQLException throwables) {
  34. throwables.printStackTrace();
  35. }
  36. return con;
  37. }
  38. public static void close(Connection con, Statement stat, ResultSet rs) {
  39. if (con != null) {
  40. try {
  41. con.close();
  42. } catch (SQLException throwables) {
  43. throwables.printStackTrace();
  44. }
  45. }
  46. if (stat != null) {
  47. try {
  48. stat.close();
  49. } catch (SQLException throwables) {
  50. throwables.printStackTrace();
  51. }
  52. }
  53. if (rs != null) {
  54. try {
  55. rs.close();
  56. } catch (SQLException throwables) {
  57. throwables.printStackTrace();
  58. }
  59. }
  60. }
  61. public static void close(Connection con, Statement stat) {
  62. if (con != null) {
  63. try {
  64. con.close();
  65. } catch (SQLException throwables) {
  66. throwables.printStackTrace();
  67. }
  68. }
  69. if (stat != null) {
  70. try {
  71. stat.close();
  72. } catch (SQLException throwables) {
  73. throwables.printStackTrace();
  74. }
  75. }
  76. }
  77. }

其实就是封装一个连接和关闭工具类方法

7. SQL注入攻击

在之前我们使用Statement对象执行sql语句并且sql语句是拼接字符串而成的 不安全

为了解决这个问题我们使用 PreparedStatement预编译执行者对象 并且参数以?形式作为占位符

为占位符 问号 赋值的方法: setXxx(参数1,参数2)

  • Xxx 为数据的类型
  • 参数1 为 ?的下标 从1开始
  • 参数2 为 ?的实际参数

内置setObject()

  1. Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql", "root", "123456");
  2. String sql = "delete from user where name = ?";
  3. PreparedStatement pstm = con.prepareStatement(sql);
  4. pstm.setString(1,"张三");

执行SQL语句

  • 执行 inser update delete 语句 executeUpdate();
  • 执行 select 语句 executeQuery();

8. 数据库连接池

数据库连接池负责分配 管理 释放数据库连接 它允许程序重复使用一个现有的数据库连接 而不是重新建立一个

9. 自定义数据库连接池

  • 继承 DataSource 接口
  • 准备一个容器 用于保存多个连接对象
  • 定义静态代码块 获取多个连接对象并放入容器中
  • 重写getConnection()方法 用于获取一个连接对象
  • 定义一个getSize方法 获取连接池容器的大小
  1. // 准备一个容器 用于保存多个连接对象
  2. private static List<Connection> pool = Collections.synchronizedList(new ArrayList<>());
  3. //定义静态代码块 获取多个连接对象并放入容器中
  4. static {
  5. for(int i=1;i<=10;i++){
  6. Connection con = JDBCUtils.getConnection();
  7. pool.add(con);
  8. }
  9. }
  10. //重写getConnection()方法 用于获取一个连接对象
  11. @Override
  12. public Connection getConnection() throws SQLException {
  13. if(pool.size() > 0 ){
  14. Connection con = pool.remove(0);
  15. return con;
  16. }else {
  17. throw new RuntimeException("连接数据已用尽");
  18. }
  19. }
  20. //定义一个getSize方法 获取连接池容器的大小
  21. public int getSize(){
  22. return pool.size();
  23. }

9.1. 归还连接

把连接对象归还给连接池

9.1.1. 继承方式

打印通过连接池创建的连对象的 class

  1. System.out.println(con.getClass());
  2. //class com.mysql.cj.jdbc.ConnectionImpl

接下定义一个类 继承 ConnectionImpl 类

  1. public class return01 extends ConnectionImpl {
  2. private Connection con;
  3. private List<Connection> pool;
  4. public return01(HostInfo hostInfo, Connection con, List<Connection> pool) throws SQLException {
  5. super(hostInfo);
  6. this.con = con;
  7. this.pool = pool;
  8. }
  9. // 重写close方法 将连接对象 重写归还容器中
  10. @Override
  11. public void close() throws SQLException {
  12. pool.add(con);
  13. }
  14. }

但DriverManager 获取的还是 ConnectionImpl 这个对象, 继承这种方法行不通的

9.1.2. 装饰设计模式

  • 实现 Connection 接口
  1. // 定义连接对象和连接容器的成员变量
  2. private Connection con;
  3. private List<Connection> pool;
  4. //通过有参构造方法为成员变量赋值
  5. public return02(Connection con,List<Connection> pool){
  6. this.con=con;
  7. this.pool=pool;
  8. }
  9. // 重写close方法
  10. @Override
  11. public void close() throws SQLException {
  12. pool.add(con);
  13. }

其他方法调用原本方法

装饰设计模式就是 重写需要的方法 其他方法则调用原来类的方法

9.1.3. 适配器设计模式

适配器设计模式 实现接口的所有方法 除了需要的方法 然后再建一个类 继承该实现类 再重新未实现的方法 (使用中间件)

  • 定义适配类 实现 Connection 接口 定义为一个抽象类
  • 定义连接对象的成员变量 Connection con
  • 通过有参构造方法赋值
  • 重写所有抽象方法 除了close
  • 继承适配类 成员变量 Connection 和 连接容器
  • 通过有参构造方法赋值
  • 重写close方法

10. 动态代理

在不改变目标对象方法的情况下对方法进行增强

被代理对象: 真实的对象

代理对象: 内容中的一个对象

代理对象必须和被代理对象实现相同的接口

  1. Student st = new Student();
  2. /*
  3. 参数1 为 类加载器 和被代理对象使用相同的类加载器
  4. 参数2 为 接口类型Class数组 和被代理对象使用相同的接口
  5. 参数3 为 代理规则 完成代理增强的功能
  6. */
  7. StudentInterface proxySt =(StudentInterface) Proxy.newProxyInstance(st.getClass().getClassLoader(), new Class[]{StudentInterface.class}, new InvocationHandler() {
  8. /*
  9. Student类中所有的方法都经过invoke方法
  10. 我们通过对方法继续判断
  11. */
  12. @Override
  13. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  14. //method为类执行某个方法 args为方法的实际参数
  15. if (method.getName().equals("study")) {
  16. // 判断为某个方法
  17. System.out.println("hello world");
  18. return null;
  19. } else {
  20. // 如不是则按原本方法执行
  21. return method.invoke(st,args);
  22. }
  23. }
  24. });
  25. // 代理对象执行方法
  26. proxySt.eat("肉");
  27. proxySt.study();

11. 以动态代理 规划连接

  1. //重写getConnection()方法 用于获取一个连接对象
  2. @Override
  3. public Connection getConnection() throws SQLException {
  4. if (pool.size() > 0) {
  5. Connection con = pool.remove(0);
  6. Connection proxycon= (Connection) Proxy.newProxyInstance(con.getClass().getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() {
  7. @Override
  8. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9. if(method.getName().equals("close")){
  10. pool.add(con);
  11. return null;
  12. }else {
  13. return method.invoke(con,args);
  14. }
  15. }
  16. });
  17. return proxycon;
  18. } else {
  19. throw new RuntimeException("连接数据已用尽");
  20. }
  21. }

12. 开源数据库连接池

12.1. C3P0

  1. 导入jar包

  2. 导入配置文件到src目录下

  3. 创建 C3P0 连接池对象

    1. DataSource dataSource=new ComboPooledDataSource();
  1. 获取数据库连接并使用
    1. Connection con = dataSource.getConnection();

配置文件会自动加载 必须命名为 c3p0-config.xml 或 c3p0-config.properties

12.2. Druid

  • 导入jar包

  • 通过properties集合 加载配置文件

    1. InputStream is = druiddemo01.class.getClassLoader().getResourceAsStream("笔记/jdbc/src/druid.properties");
    2. Properties prop =new Properties();
    3. prop.load(is);
  • 通Druid连接池工厂类获取连接池对象
    1. DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
  • 通过连接池获取数据库对象
    1. Connection con = dataSource.getConnection();

13. 自定义JDBC框架

  • DataBaseMetaData 数据库的源信息

    • getDatabaseProductName() 获取数据库产品的名称
    • getDatabaseProductVersion() 获取数据库产品的版本号
  • getParameterMetaData() 参数的源信息 预编译对象获取方法

    • getParameterCount() 获取sql语句中参数的个数
  • getMetaData() 获取结果集的源信息 通过结果集对象获取

    • getColumnCount() 获取列的总数
    • getColumnName(int i) 获取列名