一、注解
前面熟悉了MyBatis的基本使用,针对一些简单的sql语句,如对一张表的增删改查,可以使用MyBatis提供的注解,省去写映射文件的步骤,复杂的多表查询,还是建议使用映射文件的方式
1. Select注解
使用Select注解可以实现数据库查询操作
实现根据部门编号查询部门
实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept implements Serializable {
/**
* 部门编号
*/
private Integer deptno;
/**
* 部门名称
*/
private String dname;
/**
* 地址
*/
private String loc;
}
定义接口方法:
public interface DeptMapper {
/**
* 根据部门编号查询部门
* @param deptno
* @return
*/
@Select("select * from dept where deptno = #{deptno}")
Dept findDeptByDeptno(int deptno);
}
SQL语句中使用参数的方式和映射文件中相同,#{}的方式,也可以使用注解指定参数的名称
public interface DeptMapper {
/**
* 根据部门编号查询部门
* @param deptno
* @return
*/
@Select("select * from dept where deptno = #{no}")
Dept findDeptByDeptno(@Param("no") int deptno);
}
测试方法:
//根据部门编号查询部门
@Test
public void test1() {
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.findDeptByDeptno(10);
System.out.println(dept);
}
2. Insert注解
实现新增一个部门信息
定义接口方法:
/**
* 新增一个部门信息
*
* @param dept
* @return
*/
@Insert("insert into dept values(#{deptno},#{dname},#{loc})")
int addDept(Dept dept);
sql参数使用属性名
测试方法:
//新增一个部门信息
@Test
public void test2() {
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = new Dept(50,"ALGORITHM","Paris");
int rows = mapper.addDept(dept);
System.out.println(rows);
sqlSession.commit();
}
3. Update注解
实现根据部门编号更新部门信息
定义接口方法:
/**
* 根据部门编号更新部门信息
* @param dept
* @return
*/
@Update("update dept set dname = #{dname}, loc = #{loc} where deptno = #{deptno}")
int updateDept(Dept dept);
测试方法:
//根据部门编号更新部门信息
@Test
public void test3() {
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = new Dept(50,"ALGORITHM","Tokyo");
int rows = mapper.updateDept(dept);
System.out.println(rows);
sqlSession.commit();
}
4. Delete注解
实现根据部门编号删除部门
定义接口方法:
/**
* 根据部门编号删除部门
* @param deptno
* @return
*/
@Delete("delete from dept where deptno = #{deptno}")
int deleteDeptbyDeptno(int deptno);
测试方法:
//根据部门编号删除部门
@Test
public void test4() {
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
int rows = mapper.deleteDeptbyDeptno(50);
System.out.println(rows);
sqlSession.commit();
}
二、缓存配置
MyBatis自带一级缓存和二级缓存,还支持第三方缓存,如redis、ehcache
1. 一级缓存
一级缓存默认开启,存在于每个SqlSession对象中,对于完全相同的查询,如果一级缓存中存在,那么不会走数据库,直接返回
针对test1方法,通过sqlSession获取两个Mapper,并执行相同操作,最后看查询结果是否为同一对象:
//根据部门编号查询部门
@Test
public void test1() {
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.findDeptByDeptno(10);
System.out.println(dept);
DeptMapper mapper2 = sqlSession.getMapper(DeptMapper.class);
Dept dept2 = mapper2.findDeptByDeptno(10);
System.out.println(dept2);
System.out.println(dept == dept2);
}
结果:
2. 二级缓存
二级缓存可以跨SqlSession,条件是由同一个SqlSessionFactory创建,二级缓存默认关闭,开启它需要以下步骤
- 2.1 全局开关
在MyBatis核心配置文件中配置,支持二级缓存
...
- 2.2 在mapper中开启二级缓存
- java中开启方式:
在接口上使用CacheNamespace注解
@CacheNamespace
public interface DeptMapper {
- 映射文件中开启方式:
使用cache标签,并为需要开启缓存的查询设置useCache="true"
另外实体类需要实现序列化接口,因为有可能存储在磁盘中
- 2.3 SqlSession的commit或close操作
SqlSession会首先去二级缓存中查找,如果不存在,就查询数据库,commit()或者close()的时候将数据放入到二级缓存
测试方法:
public class Test1 {
private SqlSession sqlSession;
private SqlSession sqlSession2;
@Before
public void init() throws IOException {
SqlSessionFactoryBuilder sb = new SqlSessionFactoryBuilder();
// 将配置文件作为参数传入
SqlSessionFactory sqlSessionFactory = sb.build(Resources.getResourceAsStream("sqlMapConfig.xml"));
sqlSession = sqlSessionFactory.openSession();
sqlSession2 = sqlSessionFactory.openSession();
}
//根据部门编号查询部门 -- 二级缓存
@Test
public void test5() {
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.findDeptByDeptno(10);
System.out.println(dept);
sqlSession.commit();
DeptMapper mapper2 = sqlSession2.getMapper(DeptMapper.class);
Dept dept2 = mapper2.findDeptByDeptno(10);
System.out.println(dept2);
}
@After
public void release() {
if (sqlSession != null)
sqlSession.close();
if (sqlSession2 != null)
sqlSession2.close();
}
}
结果:
只执行了一条sql
3. 第三方缓存
涉及分布式系统时,MyBatis自带的缓存就不能满足需求了,下面使用Ehcache作为第三方缓存
导入依赖:
org.mybatis.caches
mybatis-ehcache
1.0.2
net.sf.ehcache
ehcache
2.10.1
org.slf4j
slf4j-nop
1.7.2
在resources目录下创建配置文件ehcache.xml:
二级缓存配置:
- Java中:
CacheNamespace注解,指定使用缓存的Class
@CacheNamespace(implementation = EhcacheCache.class)
public interface DeptMapper {
- 映射文件中:
cache标签,指定缓存的全类名
三、逆向工程
MyBatis官方提供了一个逆向工程,利用工具自动生成表对应的实体类、映射文件以及接口,并自动实现了一些基本的增删改查
1. 导入依赖:
org.mybatis.generator
mybatis-generator-core
1.3.2
2. 在resources目录下新建generatorConfig.xml:
3. 运行下面代码:
需要手动修改下,编译后target目录下generatorConfig.xml的绝对路径
public class GeneratorSqlmap {
public void generator() throws Exception {
List warnings = new ArrayList();
boolean overwrite = true;
// 需要手动修改
File configFile = new File("F:\\idelworkspace\\mybatis_study\\reverseMyBatis\\target\\classes\\generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
生成结果:
自带了一些实现:
public interface DeptMapper {
int deleteByPrimaryKey(Integer deptno);
int insert(Dept record);
int insertSelective(Dept record);
Dept selectByPrimaryKey(Integer deptno);
int updateByPrimaryKeySelective(Dept record);
int updateByPrimaryKey(Dept record);
}
项目地址:
https://gitee.com/aruba/mybatis_study.git