mybatis
我们要知道mybatis是用来处理程序连接数据库以及对数据库进行操作的组件。
消除了几乎所有jdbc代码和参数的手工设置以及结果集的检索。
思考下如何连接使用数据库呢,
以查询数据为例
1.首先加载驱动
private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/hrm?useSSL=false&&characterEncoding=utf-8";
private static final String USERNAME = "root";
private static final String PASSWORD = "123";
private static DruidDataSource ds = null;
// 加载驱动(加载一次就够了)
static {
ds = new DruidDataSource();
ds.setDriverClassName(DRIVER);
ds.setUrl(URL);
ds.setUsername(USERNAME);
ds.setPassword(PASSWORD);
ds.setMaxActive(100);// 最多能够开多少个连接
ds.setMinIdle(2);// 最少允许多少个连接处于闲置
ds.setInitialSize(2);// 初始创建多少个连接
ds.setMaxWait(10000);// 最长的等待时间
}
2.然后获取连接
Connection conn = DriverManager.getConnection();
3.开始查询
String sql ="select * from xxx where id=? and name=?";
PreparedStatement pstm= conn.prepareStatement(sql);
//防止sql注入 使用填充?的形式
for (int i = 1; i <= 2; i++) {
if (args[i - 1].getClass().getName().equals("java.util.Date"))
// 如果别人偷懒,直接传日期进来,默认按Timestamp来处理
pstm.setTimestamp(i, new java.sql.Timestamp(((java.util.Date) args[i - 1]).getTime()));
else
pstm.setObject(i, args[i - 1]);
}
List<Dept> list = new ArrayList<>();
ResultSet rs =pstm.executeQuery();
while (rs.next()) {
Dept d=new Dept();
d.setId(rs.getInt(1));
d.setName(rs.getString(2));
d.setRemark(rs.getString(3));
list.add(d);
}
4.关闭通道
Exception ex1 = null, ex2 = null, ex3 = null;
if (conn != null) {
try {
if (!conn.isClosed())
conn.close();// 在使用连接池的情形先,这个关闭是假的
} catch (Exception e) {
ex3 = null;
throw new RuntimeException("conn关闭异常", e);
}
}
if (pst != null) {
try {
pst.close();
} catch (Exception e) {
ex2 = e;
throw new RuntimeException("pst关闭异常", e);
}
}
if (rst != null) {
try {
rst.close();
} catch (Exception e) {
ex1 = e;
throw new RuntimeException("rst关闭异常", e);
}
}
if (ex1 != null || ex2 != null || ex3 != null) {
throw new RuntimeException("数据库关闭环节失败" + (ex1 != null ? ex1.getMessage() : "")
+ (ex2 != null ? ex2.getMessage() : "") + (ex3 != null ? ex3.getMessage() : ""));
}
这种操作具有很大的不便性,
- 数据库的频繁连接
- 查询时result对对象的获取
- PreparedStatement时sql语句的填充硬编码
主要使用了sqlSession来解决事务处理(statement),使用mapper.xml来解决dao对象和sql对象关系以及,增删改查时对象的注入以及获取的数据处理。最后知道mybatis是总处理文件其中有< environments >可以用来解决数据库连接问题。
一、mybatis?
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局参数设置 -->
<settings>
<!-- 开启全局的懒(延迟)加载 !!!延迟加载最好不要与缓存共存 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 关闭立即加载,其实不用配置,默认为false -->
<setting name="aggressiveLazyLoading" value="false" />
<!-- 打开二级缓存 需要基础类继承Serializable达成可序列化 和 mapper中建立标签cache -->
<setting name="cacheEnabled" value="true"/>
<setting name="logImpl" value="LOG4J"/>
</settings>
<!-- 类处理器 加载数据库所要要类属性信息 -->
<typeAliases>
<package name="com.study.it.entity"/>
</typeAliases>
<!--插件 -->
<!-- 配置数据库切面拦截器 ,用来做分页语句 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
<!-- 环境信息 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC" />
<!-- 配置数据源,采用dbcp连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/shop?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<mapper resource="mapper/TypeDaoMapper.xml" />
<mapper resource="mapper/EmpDaoMapper.xml" />
<mapper resource="mapper/GoodDaoMapper.xml" />
</mappers>
</configuration>
二、mapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.it.dao.GoodDao">
<!-- 设置缓存刷新的时间 -->
<cache flushInterval="60000" />
<resultMap type="com.study.it.entity.Good" id="basemap">
<id column="sql名称" property="实例类名称"/>
<result column="sql名称" property="实例类名称"/>
<result column="sql名称" property="实例类名称" javaType="java.sql.Date"/>
<association property="实例类名称" javaType="com.study.it.entity.实例类">
<id column="sql名称" property="实例类名称"/>
<result column="sql名称" property="实例类名称"/>
<!-- 设置懒加载查询 -->
<association property="实例类名称rec" javaType="com.study.it.entity.实例类" select="com.study.it.dao.RecDao.selectById(获取方法)" column="sql关联键名"/>
</association>
<!-- 获取外键集合,不知道什么时间用,所以用延迟加载来缓解内存 -->
<collection property="entityName" ofType="com.study.it.entity.Type" select="com.study.it.xxxDao.selectListByUser" column="sql关联键名" />
</resultMap>
<sql id="basesql">select * from xxx </sql>
<insert id="insert" useGeneratedKeys="true" keyProperty="xxx">
insert into XXX values()
</insert>
<delete id="delete">
delete from XXX where xx_id=#{id}
</delete>
<update id="update">
update XXX set xx=xx where xx_id =#{id}
</update>
<select id="selectById" resultMap="basemap">
</select>
<select id="selectOne" resultMap="basemap">
</select>
<select id="selectAll" resultMap="basemap">
<include id="basesql"/><!-- 导入前面的sql语句 -->
</select>
<select id="selectList" resultMap="basemap">
</select>
</mapper>
三、sqlSession
public void add(Type t) {
TypeDao.insertType(t);
MyBatisUtil.getSession().commit();
}
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
ThreadLocal<SqlSession> th=new ThreadLocal<SqlSession>();//等效于是Map<线程编号,SqlSession>
public static SqlSession getSession() {
SqlSession session=th.get();
if(session==null) {
session =sqlSessionFactory.openSession();
th.set(session);
}
return session;
}
public static void closeSession() {
SqlSession session=th.get();
if(session!=null) {
session.close();
th.remove();
}
}
同一个servlet可能会进行多次数据库操作,如:客户转账过程中,一个账号减钱,一个增钱、在这时若已经完成一步后出现错误,那么数据库操作不能够撤回就会导致严重的错误。这是sqlSession就提供了回滚的方法。而sqlSessionFactory也提供了多线程互不干涉的效果。
总结
我着这里还是非常浅显的理解的mybatis的过程。要深入的理解mybatis就需要去深入的了解java的反射机制。后续深入学习了反射机制后可能会过来再次加工文章。还有哪里写的不对的地方,各位大佬多多担待一些,顺便给我指出来、谢谢