1. JDBC
导入mysql-connector-java.jar包
注册驱动
Class.forName("com.mysql.jdbc.Driver");
建立连接
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql", "root", "123456");
获取对象
Statement stat = con.createStatement();
执行sql语句
String sql ="select * from help_relation";ResultSet result = stat.executeQuery(sql);
处理结果
while (result.next()){System.out.println(result.getInt("help_topic_id")+"\t"+ result.getString("help_keyword_id"));}
关闭连接
con.close();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 文件
driverClass=com.mysql.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/mysqlusername=rootpassword=123456
import java.io.IOException;import java.io.InputStream;import java.sql.*;import java.util.Properties;public class JDBCUtils {private JDBCUtils() {}//2.声明需要的配置变量private static String driverClass;private static String url;private static String usename;private static String password;private static Connection con;//3.提供静态代码块 读取配置文件为变量赋值static {try {InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");Properties prop = new Properties();prop.load(is);driverClass = prop.getProperty("driverClass");url = prop.getProperty("url");usename = prop.getProperty("usename");password = prop.getProperty("password");//注册驱动Class.forName(driverClass);} catch (Exception e) {e.printStackTrace();}}public static Connection getConnection() {try {con = DriverManager.getConnection(url, usename, password);} catch (SQLException throwables) {throwables.printStackTrace();}return con;}public static void close(Connection con, Statement stat, ResultSet rs) {if (con != null) {try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (stat != null) {try {stat.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (rs != null) {try {rs.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}public static void close(Connection con, Statement stat) {if (con != null) {try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (stat != null) {try {stat.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}
其实就是封装一个连接和关闭工具类方法
7. SQL注入攻击
在之前我们使用Statement对象执行sql语句并且sql语句是拼接字符串而成的 不安全
为了解决这个问题我们使用 PreparedStatement预编译执行者对象 并且参数以?形式作为占位符
为占位符 问号 赋值的方法: setXxx(参数1,参数2)
- Xxx 为数据的类型
- 参数1 为 ?的下标 从1开始
- 参数2 为 ?的实际参数
内置setObject()
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql", "root", "123456");String sql = "delete from user where name = ?";PreparedStatement pstm = con.prepareStatement(sql);pstm.setString(1,"张三");
执行SQL语句
- 执行 inser update delete 语句 executeUpdate();
- 执行 select 语句 executeQuery();
8. 数据库连接池
数据库连接池负责分配 管理 释放数据库连接 它允许程序重复使用一个现有的数据库连接 而不是重新建立一个
9. 自定义数据库连接池
- 继承 DataSource 接口
- 准备一个容器 用于保存多个连接对象
- 定义静态代码块 获取多个连接对象并放入容器中
- 重写getConnection()方法 用于获取一个连接对象
- 定义一个getSize方法 获取连接池容器的大小
// 准备一个容器 用于保存多个连接对象private static List<Connection> pool = Collections.synchronizedList(new ArrayList<>());//定义静态代码块 获取多个连接对象并放入容器中static {for(int i=1;i<=10;i++){Connection con = JDBCUtils.getConnection();pool.add(con);}}//重写getConnection()方法 用于获取一个连接对象@Overridepublic Connection getConnection() throws SQLException {if(pool.size() > 0 ){Connection con = pool.remove(0);return con;}else {throw new RuntimeException("连接数据已用尽");}}//定义一个getSize方法 获取连接池容器的大小public int getSize(){return pool.size();}
9.1. 归还连接
把连接对象归还给连接池
9.1.1. 继承方式
打印通过连接池创建的连对象的 class
System.out.println(con.getClass());//class com.mysql.cj.jdbc.ConnectionImpl
接下定义一个类 继承 ConnectionImpl 类
public class return01 extends ConnectionImpl {private Connection con;private List<Connection> pool;public return01(HostInfo hostInfo, Connection con, List<Connection> pool) throws SQLException {super(hostInfo);this.con = con;this.pool = pool;}// 重写close方法 将连接对象 重写归还容器中@Overridepublic void close() throws SQLException {pool.add(con);}}
但DriverManager 获取的还是 ConnectionImpl 这个对象, 继承这种方法行不通的
9.1.2. 装饰设计模式
- 实现 Connection 接口
// 定义连接对象和连接容器的成员变量private Connection con;private List<Connection> pool;//通过有参构造方法为成员变量赋值public return02(Connection con,List<Connection> pool){this.con=con;this.pool=pool;}// 重写close方法@Overridepublic void close() throws SQLException {pool.add(con);}
其他方法调用原本方法
装饰设计模式就是 重写需要的方法 其他方法则调用原来类的方法
9.1.3. 适配器设计模式
适配器设计模式 实现接口的所有方法 除了需要的方法 然后再建一个类 继承该实现类 再重新未实现的方法 (使用中间件)
- 定义适配类 实现 Connection 接口 定义为一个抽象类
- 定义连接对象的成员变量 Connection con
- 通过有参构造方法赋值
- 重写所有抽象方法 除了close
- 继承适配类 成员变量 Connection 和 连接容器
- 通过有参构造方法赋值
- 重写close方法
10. 动态代理
在不改变目标对象方法的情况下对方法进行增强
被代理对象: 真实的对象
代理对象: 内容中的一个对象
代理对象必须和被代理对象实现相同的接口
Student st = new Student();/*参数1 为 类加载器 和被代理对象使用相同的类加载器参数2 为 接口类型Class数组 和被代理对象使用相同的接口参数3 为 代理规则 完成代理增强的功能*/StudentInterface proxySt =(StudentInterface) Proxy.newProxyInstance(st.getClass().getClassLoader(), new Class[]{StudentInterface.class}, new InvocationHandler() {/*Student类中所有的方法都经过invoke方法我们通过对方法继续判断*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//method为类执行某个方法 args为方法的实际参数if (method.getName().equals("study")) {// 判断为某个方法System.out.println("hello world");return null;} else {// 如不是则按原本方法执行return method.invoke(st,args);}}});// 代理对象执行方法proxySt.eat("肉");proxySt.study();
11. 以动态代理 规划连接
//重写getConnection()方法 用于获取一个连接对象@Overridepublic Connection getConnection() throws SQLException {if (pool.size() > 0) {Connection con = pool.remove(0);Connection proxycon= (Connection) Proxy.newProxyInstance(con.getClass().getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if(method.getName().equals("close")){pool.add(con);return null;}else {return method.invoke(con,args);}}});return proxycon;} else {throw new RuntimeException("连接数据已用尽");}}
12. 开源数据库连接池
12.1. C3P0
导入jar包
导入配置文件到src目录下
创建 C3P0 连接池对象
DataSource dataSource=new ComboPooledDataSource();
- 获取数据库连接并使用
Connection con = dataSource.getConnection();
配置文件会自动加载 必须命名为 c3p0-config.xml 或 c3p0-config.properties
12.2. Druid
导入jar包
通过properties集合 加载配置文件
InputStream is = druiddemo01.class.getClassLoader().getResourceAsStream("笔记/jdbc/src/druid.properties");Properties prop =new Properties();prop.load(is);
- 通Druid连接池工厂类获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
- 通过连接池获取数据库对象
Connection con = dataSource.getConnection();
13. 自定义JDBC框架
DataBaseMetaData 数据库的源信息
- getDatabaseProductName() 获取数据库产品的名称
- getDatabaseProductVersion() 获取数据库产品的版本号
getParameterMetaData() 参数的源信息 预编译对象获取方法
- getParameterCount() 获取sql语句中参数的个数
getMetaData() 获取结果集的源信息 通过结果集对象获取
- getColumnCount() 获取列的总数
- getColumnName(int i) 获取列名
