mybatis注解多表查询
回忆:mybatis的多表查询在XML中有两种方式,一是根据根据SQL结果封装对象,二是根据调用其他接口方法的查询结果来封装对象。
多表查询离不开resultMap。
- //此注解作用是引用其他的ResultMap的id值
- public @interface ResultMap {
- String[] value();
- }
这个不是ResultMap,那么是什么呢?想一想,咱们XML配置时是resultmap+id+result。所以,是@Results。
- public @interface Results {
- String id() default "";
-
- Result[] value() default {};
- }
- public @interface Result {
- boolean id() default false;
-
- String column() default "";
-
- String property() default "";
-
- Class<?> javaType() default void.class;
-
- JdbcType jdbcType() default JdbcType.UNDEFINED;
-
- Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
-
- One one() default @One;
-
- Many many() default @Many;
- }
- public @interface One {
- String select() default "";
-
- FetchType fetchType() default FetchType.DEFAULT;
- }
- public @interface Many {
- String select() default "";
-
- FetchType fetchType() default FetchType.DEFAULT;
- }
- public enum FetchType {
- LAZY,
- EAGER,
- DEFAULT;
-
- private FetchType() {
- }
- }
我们观察这些注解定义的含义。results定义一个resultMap的id,方便@ResultMap引用。其属性@Result来定义数据库的列名称和属性之间的对应关系,对应列设置id=true。其中one对应association。many对应collection。其中的select标签对应其他接口的方法,fetchType对应(懒)加载方式。
- //接口中的代码
- @Results(id = "accountMap",value = {
- @Result(column ="id",property = "id",id = true),
- @Result(column = "uid",property = "uid"),
- @Result(column = "money",property = "money"),
- @Result(property = "user",column = "uid", one = @One(select = "dao.IUserDao.findById",fetchType = FetchType.EAGER))
- })
- @Select(value = "select * from account where id = #{id}")
- Account findById(Integer id);
- //测试代码
- @org.junit.Test
- public void test() throws IOException {
- // 4,使用SqlSession获取dao的代理对象
- IAccountDao accountDao = session.getMapper(IAccountDao.class);
- // 5,执行dao方法
- Account accountDaoById = accountDao.findById(1);
- System.out.println(accountDaoById);
- System.out.println(accountDaoById.getUser());
- }
运行结果:
我们可以看到,mybatis应用注解开发时,摒弃了XML中根据根据SQL结果封装对象,而是采用了引用其他接口的方法。这样开发更显得简单。
一对多:
- @Results(id = "userMap",value = {
- @Result(id = true,property = "id",column = "id"),
- @Result(property = "name",column = "name"),
- @Result(property = "accounts" ,column = "id",many = @Many(
- select = "dao.IAccountDao.findByUid",fetchType = FetchType.LAZY
- ))
- })
- @Select("select * from users where id = #{id}")
- User findById(Integer id);
-
- @org.junit.Test
- public void test(){
- IUserDao userDao = session.getMapper(IUserDao.class);
- User byId = userDao.findById(1);
- System.out.println(byId);
- List<Account> accounts = byId.getAccounts();
- for (Account account : accounts) {
- System.out.println(account);
- }
- }
运行结果:
是不是看起来和用起来更加简单啊!这就是应用注解的好处。
多对多的代码和这个差不多,就是两个@Result的属性都应该是many=@Many。
值得注意的是:当一个对象中属性是一个list时,往往这个属性的fetchType=FetchType.Lazy。
懒加载首先要在mybatis配置文件中配置settings哦!
- <settings>
- <!--延迟加载总开关-->
- <setting name="lazyLoadingEnabled" value="true"/>
- <!--侵入式延迟加载开关-->
- <!--3.4.1版本之前默认是true,之后默认是false-->
- <setting name="aggressiveLazyLoading" value="false"/>
- <!-- 不加这个可能有点问题-->
- <setting name="lazyLoadTriggerMethods" value=""/>
- </settings>
mybatis注解开启缓存。
一级缓存不用开启,默认开启。
二级缓存开启(注解):
<setting name="cacheEnabled" value="true"/>
还有该接口上增加注解:
- @CacheNamespace(blocking = true)
- public interface IUserDao
即可。