一、重要类对象
1.1、Resources
资源,读取资源文件。有很多方法通过加载并解析资源文件,返回不同类型的IO流对象。
1.2、sqlSessionFactoryBuilder
SqlSessionFactory的创建需要使用sqlSessionFactoryBuilder对象的build()方法。事实上使用SqlSessionFactoryBuilder的原因是将SqlSessionFactory这个复杂对象的创建交给Builder来执行,也就是建造者模式。
建造者模式:又称生成器模式,是一种对象的创建模式。可以将一个产品的内部表象与生成过程分割开,从而可以使一个建造过程生成具有不同内部表象的产品(将一个复杂对象的构建与它的表示分离,使得同样的构建可以创建不同的表示) 这样用户只需要指定需要建造的类型就可以得到具体的产品,不需要了解具体的建造过程和细节
在建造者模式中,角色分为指导者(Director)和建造者(builder):用户联系指导者,指导者指挥建造者最终得到产品。建造者模式可以强制执行分步骤建造过程。
1.3、SqlSessionFactory
SqlSessionFactory是一种重量级对象(系统开销大的对象),线程安全,所以一个应用只需要一个该对象即可。创建SqlSession对象使用SqlSessionFactory接口的openSession()方法。
默认的openSession()方法没有参数,它创建有如下特性的SqlSession对象:
- 开启一个事务(不自动提交)
- 将从由当前环境配置的DataSource实例中获取connection对象,事务隔离级别将会使用驱动或者数据源的默认设置。
- 预处理语句不会被复用,也不会处理批量更新。
- openSession(true) 创建一个有自动提交的SqlSession
- openSession(false) 创建一个非自动提交的SqlSession,即需要手动提交
- openSession() 同openSession(false)
1.4、SqlSession
SqlSession对象用于执行持久化操作,一个SqlSession对应着一次数据库会话。一次会话以SqlSession的创建开始,以SqlSession的关闭结束。
SqlSession对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其close()方法将其关闭。再次需要会话,再次开启。
SqlSession内部超过20个方法,我们常用的都是执行语法相关的方法。这些方法被用来执行定义在Sql映射的XML文件中SELECT、UPDATE、INSERT、DELETE语句,他们都会自行解释,每一句都使用语句的ID属性和参数对象,参数可以是原生类型(自动装箱或包装类)、JavaBean、PoJo或者Map。
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
二、Mybatis框架
- mybatis.xml是Mybatis框架的全局配置文件,配置了Mybatis运行的框架信息。Mapper1.xml…是Sql映射文件,配置了所有操作数据库的语句。这些文件需要在全局配置中加载。
- 通过Mybatis.xml等配置信息构建SqlSessionFactory,相当于产生连接池。
- 由SqlSessionFactory会话工厂创建SqlSession会话,进行数据库操作。
- Mybatis底层定义了Excutor执行器的接口操作数据库,Excutor接口有两个实现,基本执行器和缓存执行器。
- MappedStatement也是Mybatis的底层封装对象, 它包装了Mybatis配置信息以及sql映射信息,Mapper.xml中一个Sql语句对应一个Mapped Statement,sql的ID就是Mapped Statement的id。
- Mapped Statement对sql执行输入参数定义,输入参数包括HashMap、基本类型、pojo,Excutor在Mapped Statement执行Sql语句前将输入java对象映射到sql语句中,执行sql完毕后,输出映射就是JDBC中编码中对prepareStatement执行结果的定义。
三、配置日志
3.1、添加pom依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
3.2、添加log4j.properties配置文件
#Global logging configuration info warning error
log4j.rootLogger=DEBUG,stdout
#console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3.3、添加mybatis.xml配置
<configuration>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
...
</configuration>
3.4、测试结果
四、使用dao方式开发Mybatis项目
4.1、ThreadLocal
ThreadLocal并非一个线程的本地实现版本,它并不是一个Thread,而是一个threadlocalvariable(线程局部变量)。它的功能十分简单,为每一个使用该变量的线程都提供一个变量值副本,是java中较为特殊的一种线程绑定机制,其中每一个线程都可以独立的改变自己的副本,而不会与其他线程副本冲突。
4.2、SqlSession工具类
public class MybatisUtil {
private static ThreadLocal<SqlSession> threadLocal=new ThreadLocal<>();
private static SqlSessionFactory sqlSessionFactory;
static {
try {
Reader reader = Resources.getResourceAsReader("mybatis.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
SqlSession sqlSession=threadLocal.get();
if(sqlSession==null){
sqlSession = sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
public static void closeSqlSession(){
SqlSession sqlSession=threadLocal.get();
if(sqlSession==null){
sqlSession.close();
threadLocal.remove();
}
}
}
4.3、dao接口和实现类
public interface TeamDao {
List<Team> queryAll();
Team queryById(Integer teamId);
Integer add(Team team);
Integer update(Team team);
Integer delete(Integer teamId);
}
public class TeamDaoImpl implements TeamDao {
@Override
public List<Team> queryAll() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
List<Team> list = sqlSession.selectList("com.jsonliu.test.entity.Team.queryAll");
MybatisUtil.closeSqlSession();
return list;
}
@Override
public Team queryById(Integer teamId) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
Team team=sqlSession.selectOne("com.jsonliu.test.entity.Team.queryById",teamId);
MybatisUtil.closeSqlSession();
return team;
}
@Override
public Integer add(Team team) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
int num = sqlSession.insert("com.jsonliu.test.entity.Team.insert", team);
sqlSession.commit();
MybatisUtil.closeSqlSession();
return num;
}
@Override
public Integer update(Team team) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
int num =sqlSession.update("com.jsonliu.test.entity.Team.update",team);
sqlSession.commit();
MybatisUtil.closeSqlSession();
return num;
}
@Override
public Integer delete(Integer teamId) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
int num =sqlSession.delete("com.jsonliu.test.entity.Team.delete",teamId);
sqlSession.commit();
MybatisUtil.closeSqlSession();
return num;
}
}
4.4、测试类
public class TestB {
private TeamDao teamDao=new TeamDaoImpl();
@Test
public void test1(){
System.out.println("------------------queryAll----------------------");
List<Team> teams = teamDao.queryAll();
teams.forEach(team -> {
System.out.println(team);
});
System.out.println("------------------add----------------------");
Integer insert = teamDao.add(new Team("探险者", "新泽西", new Date()));
System.out.println("新增结果:"+insert);
System.out.println("------------------query----------------------");
Team team = teamDao.queryById(1115);
System.out.println(team);
System.out.println("------------------update----------------------");
team.setTeamName("JK的队伍");
team.setLocation("hangzhou");
Integer update = teamDao.update(team);
System.out.println("修改结果:"+insert);
System.out.println("------------------delete----------------------");
Integer delete = teamDao.delete(1115);
System.out.println("删除结果:"+delete);
}
}
五、使用mapper方式开发Mybatis项目
5.1、什么是mapper接口
前面的例子中,dao实现类并没做什么实质性的事情,仅仅通过sqlSession的相关API定位到mapper中相应id的sql语句。真正对DB进行操作是Mapper中的SQL完成的。
所以,Mybatis抛开了dao的实现类,直接定位到映射文件mapper中相应的sql语句,对DB进行操作。这种Dao的实现方式被称为Mapper接口的动态代理实现。
Mapper动态代理无需程序员实现dao接口,接口是Mybatis结合映射文件生成的动态代理实现的。
5.2、TeamMapper
public interface TeamMapper {
List<Team> queryAll();
Team queryById(Integer teamId);
Integer insert(Team team);
Integer update(Team team);
Integer delete(Integer teamId);
}
5.3、TeamMapper.xml
<?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.jsonliu.test.mapper.TeamMapper">
<select id="queryAll" resultType="com.jsonliu.test.entity.Team">
select * from team
</select>
<select id="queryById" parameterType="int" resultType="com.jsonliu.test.entity.Team">
select * from team where teamId=#{id}
</select>
<insert id="insert" parameterType="com.jsonliu.test.entity.Team">
insert into team(teamName,location,createTime)
values(#{teamName},#{location},#{createTime})
</insert>
<update id="update" parameterType="com.jsonliu.test.entity.Team">
update team set teamName=#{teamName},location=#{location} where teamId=#{teamId}
</update>
<delete id="delete" parameterType="int">
delete from team where teamId=#{teamId}
</delete>
</mapper>
5.4、mybatis配置文件中添加mapper
<configuration>
...
<mappers>
<mapper resource="com/jsonliu/test/entity/Team.xml"/>
<mapper resource="com/jsonliu/test/mapper/TeamMapper.xml"/>
</mappers>
</configuration>
5.5、getMapper()获取代理对象
只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。
public class TeamMapperTest {
@Test
public void test1(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
TeamMapper teamDao = sqlSession.getMapper(TeamMapper.class);
System.out.println("------------------queryAll----------------------");
List<Team> teams = teamDao.queryAll();
teams.forEach(team -> {
System.out.println(team);
});
System.out.println("------------------add----------------------");
Integer insert = teamDao.insert(new Team("探险者23", "新泽西23", new Date()));
System.out.println("新增结果:"+insert);
System.out.println("------------------query----------------------");
Team team = teamDao.queryById(1116);
System.out.println(team);
System.out.println("------------------update----------------------");
team.setTeamName("wangwu的队伍");
team.setLocation("tianjin");
Integer update = teamDao.update(team);
System.out.println("修改结果:"+insert);
System.out.println("------------------delete----------------------");
Integer delete = teamDao.delete(1116);
System.out.println("删除结果:"+delete);
}
}
5.6、实现原理
|