今日内容
- 自定义数据库连接池
- mybatis
自定义数据库连接池
- 实现DataSource接口(这是JDBC定义的规范)
- 用什么集合来存储链接(Connection),List
- 什么时候创建链接存放到datasources集合里面
- 如何从自定义连接池中获取链接,getConnection
- 关闭链接不是将链接归还到连接池,而是直接关闭
装饰者模式
- 作用:在不改变原有类的情况下增强原有类的功能
- 原有类:A
- LoggingA:装饰者类‘
- KTV: 唱歌
- HeimaKTV: 实现了KTV的基础功能,有唱歌功能
- 需求:除了基本的唱歌功能,还需要灯光效果(不改变原有类代码)
- 继承
- 装饰
- 装饰:
- 本地不变还是KTV(实现KTV规范)
- 需要基础KTV属性字段
- 添加灯光效果
- 总结:
- 装饰者以及被装饰者应该是同一个类型
- 如果被装饰者有功能实现那么自己不再重复实现直接使用被装饰者的功能,
- 装饰者需要做的只是其他额外功能的实现
目的:
- 装饰Connection链接对象,实现close方法的增强
MyConnetion1
- 目的: 重写close方法将链接归还到连接池
- 字段
- 链接
- 链接池
- 被装饰者:private Connection con;
适配器模式
- 对象:
- 目标接口(我们想要什么类型)
- 已存在实现(网线接口)
- 适配(实现目标接口, 继承已有实现)
- 目标
- 已有sports接口(这是目标类型), 目前系统已有SportsExercise但其没有实现Sports接口;我要利用已有的实现,并且符合Sports规范
动态代理模式
- 代理出来的对象和原本被代理对象没有任何关系, 只不过他们都有相同接口
- 如果遇到不想增强的方法那么我们可以利用反射调用被代理对象的方法(这才是产生关联的原因)
//自定义连接池
import java.sql.Connection;
import java.sql.SQLException;
public class Demo {
public static void main(String[] args) throws SQLException {
//打印连接池数量
myDataSource myDataSource=new myDataSource();
System.out.println(myDataSource.getSize());//10
//获取连接并打印地址值
Connection connection = myDataSource.getConnection();
System.out.println(connection);
//打印连接池数量
System.out.println(myDataSource.getSize());//9
//释放资源
connection.close();//所以使用的是默认关闭,而不是归还连接,下面解决用动态代理
//再次打印连接池数量
System.out.println(myDataSource.getSize());//9
//循环获取10次连接,最后打印连接数量
}
}
import utils.JDBCUtils;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
//自定义数据库连接池获取连接
//实现datasource接口
public class myDataSource implements DataSource {
// javax.sql.DataSource 接口:数据源(数据库连接池)。Java 官方提供的数据库连接池规范(接口)
private List<Connection> datasources;
public myDataSource() {
datasources=new ArrayList<>();
//在构造方法中初始化datasources,默认创建10个连接对象存入datasources集合
for (int i = 0; i < 10; i++) {
Connection connection= JDBCUtils.getConnection();
datasources.add(connection);
}
}
//用于获取当前数据库连接池的个数
public int getSize(){
return datasources.size();
}
@Override
public Connection getConnection() throws SQLException {
if (datasources.size()>0){
Connection connection = datasources.get(0);
//将获取的连接暂时从连接池中移出
datasources.remove(0);
//采用动态代理,来归还自定义连接池中取出连接后归还连接,也就是单独增强close方法,来达到不是普通关闭,是归还到连接池
Connection proxyconnection = (Connection) Proxy.newProxyInstance(connection.getClass().getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("close")) {
//归还连接
datasources.add(connection);
return null;
} else {
return method.invoke(connection, args);
}
}
});
return proxyconnection;
}else{
throw new RuntimeException("连接数量已用尽");
}
}
自定义数据库连接池
- 怎么存储多个数据库链接
- 顶一个List的集合
- 需不需要实现JDBC的规范
- 实现DataSource接口
- 什么时候获取数据库链接存入集合
- 构造方法
- 静态代码块
- 获取链接方法的实现
- list.get(0)
- 从集和中移除对应的链接
- 关闭链接问题
- 装饰者模式
- 适配器模式
- 动态代理模式
Mybatis
- 作用:就是对JDBC代码进行封装
orm
- 数据库表结构 == 实体类
- 表字段 == 成员变量(属性)
- 表的一行记录 == 创建的一个对象
Mybatis Hello world
-
导包
-
定义全局配置文件
- 定义数据库链接信息(定义数据库链接池)
- 加载SQL映射文件
-
SQL映射文件
-
编写java代码
- 加载配置文件
- 获取SQLSession
- SqlSessionFactoryBuilder, 读取输入流构建SQLSessionFacotry
- 通过SQLSessionFactory构建SQLSession
-
mybatis当中所有的信息基本上都和Configuration对象关联
ResourceAPI
- 作用:就是加载配置文件为InputStream,底层实现实际上就是利用ClassLoader的个天ResourceAsS太热安
SqlSessionFactoryBuilder
- 作用: 主要解析配置文件,然后构建SQLSessionFactory
SqlSessionFactory
- openSession() : 创建SQLSession并且默认不会自动提交事务
- openSession(bool): 如果bool为true事务自动提交
SQLSession
- 增删改
- 查询
- selectList
- selectOne
- 事务
- 关闭资源
多个Mapper的情况
- Student
- selectAll
- Teacher
- selectAll
Mapper标签
- 属性: namespace, 理解为包名
select标签
- 名字: name
- 返回值类型: resultType
- 参数类型:parameterType
- 方法体:SQL语句
mybatis–> SQL + parameterType ----> ResultSet —> resultType
- 为什么mybatis中查询的结果是集合不写List
- mybatis通过方法(selectList、selectOne)来判断最后结果是集合还是对象,你只需要传递你真正数据表对应的类型即可
insert
- 注意:
- 返回值类型可以省略,默认整型
- 如果参数类型为引用数据类型,直接写属性名称即可
- 事务默认不是自动提交
- 手动提交SQLSession.commit()
- 创建事务时传递true参数