MyBatis from entry to the master (III): basic usage MyBatis XML way as much as table query

Liuzeng Hui teacher recently read the book "MyBatis from entry to the master," a book, rewarding, so the learning process of their own output in a blog format, if wrong, please correct me, as to help you, honored!

1. Multi-table query

Part blog, we have the example of two single-table queries are queries, but the actual business scene definitely need to multi-table queries, such as now there is a demand:

Discover all the roles a user owns. This needs to be involved sys_user, sys_user_role, sys_role three tables, how to achieve it?

First, a method is defined in SysUserMapper interface.

/**
 * 根据用户id获取角色信息
 *
 * @param userId
 * @return
 */
List<SysRole> selectRolesByUserId(Long userId);

SysUserMapper.xml then open the corresponding file, add the following select statement:

<select id="selectRolesByUserId" resultType="com.zwwhnly.mybatisaction.model.SysRole">
    SELECT r.id,
           r.role_name   roleName,
           r.enabled,
           r.create_by   createBy,
           r.create_time createTime
    FROM sys_user u
    INNER JOIN sys_user_role ur ON u.id = ur.user_id
    INNER JOIN sys_role r ON ur.role_id = r.id
    WHERE u.id = #{userId}
</select>

Careful readers may find, though we use to multi-table queries, but is still set resultType single table that contains only information character table.

If I want this query and returns user_name field SysUser watch it, how to set resultType?

Method 1 : userName fields added directly SysRole entity class.

private String userName;

public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

At this point resultType without modification.

Method 2: Create extended by adding class userName field extension.

package com.zwwhnly.mybatisaction.model;

public class SysRoleExtend extends SysRole {
    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

At this point you need to be revised to resultType: com.zwwhnly.mybatisaction.model.SysRoleExtend.

This approach is more suitable field needs a few extra scenes. If you need to field a large number of other tables, you can use 3 or 4 way, personally recommend using Mode 4.

Method 3: Add SysUser type field SysRole entity classes.

private SysUser sysUser;

public SysUser getSysUser() {
   return sysUser;
}

public void setSysUser(SysUser sysUser) {
    this.sysUser = sysUser;
}

At this point resultType without modification.

Method 4 (recommended) : new extension of the class, the class is added in the extension type field SysUser.

The book is recommended by 3 way, 4 way I personally think that a better way, because the entity classes are generally generated by the tool automatically adds the field, leading to follow-up is easy to forget is overwritten.

package com.zwwhnly.mybatisaction.model;

public class SysRoleExtend extends SysRole {
    private SysUser sysUser;

    public SysUser getSysUser() {
        return sysUser;
    }

    public void setSysUser(SysUser sysUser) {
        this.sysUser = sysUser;
    }
}

At this point you need to be revised to resultType: com.zwwhnly.mybatisaction.model.SysRoleExtend.

At this point xml query statement is as follows.

<select id="selectRolesByUserId" resultType="com.zwwhnly.mybatisaction.model.SysRoleExtend">
    SELECT r.id,
           r.role_name   roleName,
           r.enabled,
           r.create_by   createBy,
           r.create_time createTime,
           u.user_name   "sysUser.userName",
           u.user_email   "sysUser.userEmail"
    FROM sys_user u
    INNER JOIN sys_user_role ur ON u.id = ur.user_id
    INNER JOIN sys_role r ON ur.role_id = r.id
    WHERE u.id = #{userId}
</select>

Add the test code SysUserMapperTest follows.

@Test
public void testSelectRolesByUserId() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        List<SysRole> sysRoleList = sysUserMapper.selectRolesByUserId(1L);

        Assert.assertNotNull(sysRoleList);
        Assert.assertTrue(sysRoleList.size() > 0);
    } finally {
        sqlSession.close();
    }
}

Run the test method, as input log.

DEBUG [main] - ==> Preparing: SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime, u.user_name "sysUser.userName", u.user_email "sysUser.userEmail" FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.id WHERE u.id = ?

DEBUG [main] - ==> Parameters: 1(Long)

TRACE [main] - <== Columns: id, roleName, enabled, createBy, createTime, sysUser.userName, sysUser.userEmail

TRACE [main] - <== Row: 1, the administrator, 1, 1, 2019-06-27 18: 21: 12.0, admin, [email protected]

TRACE [main] - <== Row: 2, ordinary users, 1, 1, 2019-06-27 18: 21: 12.0, admin, [email protected]

DEBUG [main] - <== Total: 2

2. The use of multiple interface parameters

2.1 parameter type is primitive

Up to now, the way we have defined only one parameter, either only one type of basic parameters, such as selectById (Long id) ;.

Either only an object as a parameter, is about more parameters merged into one object.

But in some scenarios, such as only two parameters, it is not necessary for these two parameters and then create a new object, such as we now need to get all the roles the user id of the user based on the status and roles, then how to use it?

First, a method of adding the interface SysUserMapper.

/**
 * 根据用户id和角色的enabled状态获取用户的角色
 *
 * @param userId
 * @param enabled
 * @return
 */
List<SysRole> selectRolesByUserIdAndRoleEnabled(Long userId,Integer enabled);

Then, SysUserMapper.xml open the corresponding file, add the following code.

<select id="selectRolesByUserIdAndRoleEnabled" resultType="com.zwwhnly.mybatisaction.model.SysRole">
    SELECT r.id,
           r.role_name   roleName,
           r.enabled,
           r.create_by   createBy,
           r.create_time createTime
    FROM sys_user u
    INNER JOIN sys_user_role ur ON u.id = ur.user_id
    INNER JOIN sys_role r ON ur.role_id = r.id
    WHERE u.id = #{userId} AND r.enabled = #{enabled}
</select>

In SysUserMapperTest test class, add the following test methods.

@Test
public void testselectRolesByUserIdAndRoleEnabled() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);
        List<SysRole> sysRoleList = sysUserMapper.selectRolesByUserIdAndRoleEnabled(1L, 1);

        Assert.assertNotNull(sysRoleList);
        Assert.assertTrue(sysRoleList.size() > 0);
    } finally {
        sqlSession.rollback();
        sqlSession.close();
    }
}

Run this test method, the following error report found.

Not Found error message says parameter userId, the available parameters are [0,1, param1, param2], which means we will modify the code as follows:

WHERE u.id = #{0} AND r.enabled = #{1}

Or amended as follows:

WHERE u.id = #{param1} AND r.enabled = #{param2}

So by using a test, but such use, the code is not friendly enough to read it, so therefore not recommended to use.

Recommended to add annotations before @Param interface method parameters, as follows:

/**
 * 根据用户id和角色的enabled状态获取用户的角色
 *
 * @param userId
 * @param enabled
 * @return
 */
List<SysRole> selectRolesByUserIdAndRoleEnabled(@Param("userId") Long userId, @Param("enabled") Integer enabled);

Test method is run just added, the test passes, the output log is as follows:

DEBUG [main] - ==> Preparing: SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.id WHERE u.id = ? AND r.enabled = ?

DEBUG [main] - ==> Parameters: 1(Long), 1(Integer)

TRACE [main] - <== Columns: id, roleName, enabled, createBy, createTime

TRACE [main] - <== Row: 1, the administrator, 1, 1, 2019-06-2718: 21: 12.0

TRACE [main] - <== Row: 2, ordinary users, 1, 1, 2019-06-2718: 21: 12.0

DEBUG [main] - <== Total: 2

2.2 parameter type is Object

To demonstrate the parameter type is to use an object, we add the following method in the interface SysUserMapper:

/**
 * 根据用户id和角色的enabled状态获取用户的角色
 *
 * @param user
 * @param role
 * @return
 */
List<SysRole> selectRolesByUserAndRole(@Param("user") SysUser user, @Param("role") SysRole role);

At this time, corresponding to the statement xml:

<select id="selectRolesByUserAndRole" resultType="com.zwwhnly.mybatisaction.model.SysRole">
    SELECT r.id,
    r.role_name   roleName,
    r.enabled,
    r.create_by   createBy,
    r.create_time createTime
    FROM sys_user u
    INNER JOIN sys_user_role ur ON u.id = ur.user_id
    INNER JOIN sys_role r ON ur.role_id = r.id
    WHERE u.id = #{user.id} AND r.enabled = #{role.enabled}
</select>

3. Source

Source Address: https://github.com/zwwhnly/mybatis-action.git , welcome to download.

4. Reference

Liuzeng Hui "MyBatis from entry to the master."

Guess you like

Origin www.cnblogs.com/zwwhnly/p/11124577.html