mybatis注解开发-复杂的结果集映射

实现复杂关系映射之前我们可以在映射文件中通过配置来实现,在使用注解开发时我们需要借助@Results 注解,@Result 注解,@One 注解,@Many 注解。

一、复杂关系映射的注解

1. @Results注解

该注解代替的是标签 <resultMap> ;该注解中可以使用单个@Result注解,也可以使用@Result集合

@Results(@Result)

# 或者

@Results({
    @Result(),
    @Result()
})

2. @Result注解

代替了 <id> 标签和 <result> 标签;@Result中属性介绍如下

属性 描述
id 是否为主键字段
column 数据库查询出的列名
property 需要装配的属性名
one 需要使用的@One注解 @Result(one=@One)
many 需要使用的@Many注解 @Result(many=@many)

3. @One注解(一对一)

代替了 <association> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。

  1. @One注解属性(取不同的值)介绍(注解内容的注解?)
  • select: 指定多表查询的sqlmapper
  • fetchType: 会覆盖全局的配置参数lazyLoadingEnable…
  1. 使用格式
@Result(column="", property="",one=@One(select=""))

4. Many注解(多对一)

代替了 <Collection> 标签,是多表查询的关键,在注解中来指定子查询返回对象集合。注意,聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList),但是注解中可以不定义。

  1. 使用格式
@Result(property="",column="",many=@Many(select=""))

公共配置

  1. SqlMapConfig.xml
<?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>
    <properties resource="JdbcConfig.properties"></properties>
    <typeAliases>
        <package name="com.itheima.domain"></package>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 配置dao接口的位置
     1. 使用mapper标签配置class属性
     2. 使用package标签,直接指定dao接口所在的包
     -->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>
  1. User pojo
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;

private List<Account> accounts;
  1. Account pojo
private Integer id;
private Integer uid;
private Double money;

private User user;
  1. 测试方法
InputStream in;
       SqlSessionFactory factory;
       SqlSession session;
       AccountDao accountDao;
       UserDao userDao;

       @Before
       public void init() throws Exception {
           in = Resources.getResourceAsStream("SqlMapConfig.xml");
           factory = new SqlSessionFactoryBuilder()
                   .build(in);
           session = factory.openSession();
           accountDao = session.getMapper(AccountDao.class);
       }

       @After
       public void destroy() throws Exception {
           session.commit();
           session.close();
           in.close();
       }
       ...

三、使用注解实现一对一复杂关系映射以及延迟加载

比如,账户信息和用户信息是多对一的关系,加载账户信息并且加载该账户的用户信息。

  1. AccountDao 接口方法 findAll
/** 查询所有账户,采用延迟加载的方式查询账户的所属用户 */

@Select("select * from account")
@Results(id="accountMap",
    value = {
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "uid", property = "uid"),
            @Result(column = "money", property = "money"),
            @Result(column = "uid", property = "user",
                    one = @One(select = "com.itheima.dao.UserDao.findById",
                                fetchType = FetchType.LAZY // 懒加载
                    )
            )
    }
)
List<Account> findAll();
  1. UserDao中的接口方法 findById
/** 根据id查询一个用户 */
@Select("select * from user where id = #{uid}")
@Results(id="userMap",
        value = {
                @Result(id=true, column="id",property = "userId"),
                @Result(column = "username", property = "userName"),
                @Result(column = "sex", property = "userSex"),
                @Result(column = "address", property = "userAddress"),
                @Result(column = "birthday", property = "userBirthday")
        })
User findById(Integer userId);
  1. 测试方法
List<Account> all = accountDao.findAll();
for (Account account : all) {
    System.out.println(account);
    System.out.println(account.getUser());
}

四、使用注解实现一对多复杂关系映射

user与account表示一对多的关系;查询用户信息时,也要查询关联的所有账户列表

  1. UserDao 接口方法 findAll
/** 查询所有用户 */
@Select("select * from user")
@Results(id="userMap",
        value = {
                @Result(id=true, column="id",property = "userId"),
                @Result(column = "username", property = "userName"),
                @Result(column = "sex", property = "userSex"),
                @Result(column = "address", property = "userAddress"),
                @Result(column = "birthday", property = "userBirthday"),
                @Result(column = "id", property = "accounts",
                        many = @Many(
                                select = "com.itheima.dao.AccountDao.findByUid",
                                fetchType = FetchType.LAZY // 懒加载
                        )
                )
        })
List<User> findAll();
  1. AccountDao 接口方法 findByUid
@Select("select * from account")
@Results(id="accountMap",
    value = {
            @Result(id=true, column = "id", property = "id"),
            @Result(column = "uid", property = "uid"),
            @Result(column = "money", property = "money"),
            @Result(column = "uid", property = "user",
                    one = @One(select = "com.itheima.dao.UserDao.findById",
                                fetchType = FetchType.LAZY
                    )
            )
    }
)
List<Account> findAll();

@Select("select * from account where uid = #{uid}")
@ResultMap("accountMap")
List<Account> findByUid(Integer uid);
  1. 测试方法
List<User> all = userDao.findAll();
for (User user : all) {
    System.out.println(user);
    System.out.println(user.getAccounts());
}

五、参数注解传递参数

  1. UserDao 接口方法
/** 注解参数案例 */
@Select("select * from user where username like #{pName} and address like #{pAddr}")
@ResultMap("userMap") // 复用上面【四】的ResultMap,而且还有懒加载功能
List<User> findbyNameAndAddress(@Param("pName") String name, @Param("pAddr") String address);
  1. 测试方法
/** 测试注解参数 */
@Test
public void testFindByNameAndAddr() {
    List<User> users = userDao.findbyNameAndAddress("%王%", "%北京%");
    for (User user : users) {
        System.out.println(user);
    }
}

原文:https://www.jianshu.com/p/7f2a160ca97d
作者: 哈哈大圣