Bootstrap

第十章 Mybatis之注解开发

目录

一、引言

二、常规XML完成CRUD

2.1. 用户实体类

2.2. UserMapper 

2.3. sqlMapConfig.xml

2.4. properties  

2.5. UserMapper.xml 

2.6. 测试类 

三、注解完成CRUD 

3.1. UserMapper 

3.2. sqlMapConfig.xml

四、注解实现复杂映射开发

4.1. 一对一查询模式(1) 

4.1.1. OrderMapper

4.1.2. sqlMapConfig.xml

4.1.3. properties

4.1.4. 订单实体类

4.1.5. 用户实体类

4.1.6. 测试类

4.2. 一对一查询模式(2) 

4.3. 一对多查询模型

4.3.1. sqlMapConfig.xml

4.3.2. properties

4.3.3. UserMapper

4.3.4. OrderMapper

4.3.5. Order实体类

4.3.6. User实体类

4.4. 多对多查询模型

4.4.1. sqlMapConfig.xml

4.4.2. properties

4.4.3. UserMapper

4.4.4. RoleMapper

4.4.5. Role实体类

4.4.6. User实体类


一、引言

MyBatis 注解开发是指在 MyBatis 中使用注解来代替 XML 配置文件的方式,通过使用注解开发方式,这样我们就可以减少编写Mapper.xml映射文件了。

@Insert:执行新增操作

@Update:执行更新操作

@Delete:执行删除操作

@Select:执行查询操作,返回查询结果。

@Result:执行结果集封装

@Results:可以与@Result 一起使用,封装多个结果集。

@One:实现一对一结果集封装

@Many:实现一对多结果集封装

二、常规XML完成CRUD

2.1. 用户实体类

package com.example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
    private int id;
    private String username;
    private String password;
    private Date birthday;
}

2.2. UserMapper 

package com.example.mapper;

import com.example.domain.User;
import java.util.List;

public interface UserMapper {

    void save(User user);

    void update(User user);

    void delete(int id);

    User findById(int id);

    List<User> findAll();
}

2.3. sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 加载外部properties -->
    <properties resource="jdbc.properties"></properties>

    <settings>
        <!-- 其他配置 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <typeAlias type="com.example.domain.User" alias="user"></typeAlias>
    </typeAliases>

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 指定方言 MySQl -->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
    
    <!-- 数据源环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 加载映射文件 -->
    <mappers>
        <mapper resource="com/example/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

2.4. properties  

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=Wangzhexiao

2.5. UserMapper.xml 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">

    <insert id="save" parameterType="user">
        insert into user values(#{id},#{username},#{password},#{birthday})
    </insert>

    <update id="update" parameterType="user">
        update user set username = #{username}, password = #{password} where id = #{id}
    </update>

    <delete id="delete" parameterType="int">
        delete from user where id = #{id}
    </delete>

    <select id="findById" parameterType="int" resultType="user">
        select * from user where id = #{id}
    </select>

    <select id="findAll" resultType="user">
        select * from user
    </select>
</mapper>

2.6. 测试类 

package com.example;

import com.example.domain.User;
import com.example.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

public class UserTest {

    private UserMapper userMapper;

    @Before
    public void before() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new
                SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void insert() {
        User user = new User();
        user.setUsername("余则成");
        user.setPassword("yuzecheng");
        user.setBirthday(new Date());
        userMapper.save(user);
    }

    @Test
    public void delete() {
        userMapper.delete(11);
    }

    @Test
    public void update() {
        User user = new User();
        user.setId(1);
        user.setUsername("毛泽东");
        user.setPassword("maozedong");
        user.setBirthday(new Date());
        userMapper.update(user);
    }

    @Test
    public void findById() {
        userMapper.findById(1);
    }

    @Test
    public void findAll() {
        userMapper.findAll();
    }
}

三、注解完成CRUD 

上述XML方式CRUD其他相关代码不变,我们仅删除UserMapper.xml,将其中的SQL通过注解的方式,添加到UserMapper接口中的各个对应的方法上,以及将sqlMapConfig.xml中对UserMapper.xml的配置改为UserMapper接口:

3.1. UserMapper 

package com.example.mapper;

import com.example.domain.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

public interface UserMapper {

    @Insert("insert into user values(#{id},#{username},#{password},#{birthday})")
    void save(User user);

    @Update("update user set username = #{username}, password = #{password} where id = #{id}")
    void update(User user);

    @Delete("delete from user where id = #{id}")
    void delete(int id);

    @Select("select * from user where id = #{id}")
    User findById(int id);

    @Select("select * from user")
    List<User> findAll();
}

3.2. sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 加载外部properties -->
    <properties resource="jdbc.properties"></properties>

    <settings>
        <!-- 其他配置 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <typeAlias type="com.example.domain.User" alias="user"></typeAlias>
    </typeAliases>

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 指定方言 MySQl -->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
    
    <!-- 数据源环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 加载映射关系 -->
    <mappers>
        <!-- 指定接口所在的包 -->
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

查看最终控制台输出结果,效果和XML方式一样。

四、注解实现复杂映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置。

4.1. 一对一查询模式(1) 

4.1.1. OrderMapper

package com.example.mapper;

import com.example.domain.Order;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface OrderMapper {

    @Select("select *, o.id oid from `order` o, user u where o.uid = u.id")
    @Results({
            @Result(column = "oid", property = "id"),
            @Result(column = "ordertime", property = "orderTime"),
            @Result(column = "total", property = "total"),
            @Result(column = "uid", property = "user.id"),
            @Result(column = "username", property = "user.username"),
            @Result(column = "password", property = "user.password"),
    })
    List<Order> findAll();
}

4.1.2. sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 加载外部properties -->
    <properties resource="jdbc.properties"></properties>

    <settings>
        <!-- 其他配置 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <typeAlias type="com.example.domain.User" alias="user"></typeAlias>
    </typeAliases>

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 指定方言 MySQl -->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
    
    <!-- 数据源环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 加载映射关系 -->
    <mappers>
        <!-- 指定接口所在的包 -->
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

4.1.3. properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=Wangzhexiao

4.1.4. 订单实体类

package com.example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Order {

    private int id;
    private Date orderTime;
    private double total;
    private User user;
}

4.1.5. 用户实体类

package com.example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
    private int id;
    private String username;
    private String password;
    private Date birthday;
}

4.1.6. 测试类

package com.example;

import com.example.domain.Order;
import com.example.mapper.OrderMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UserTest {

    private OrderMapper orderMapper;

    @Before
    public void before() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new
                SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        orderMapper = sqlSession.getMapper(OrderMapper.class);
    }

    @Test
    public void findAll() {
        List<Order> orders = orderMapper.findAll();
        for (Order order : orders) {
            System.out.println(order);
        }
    }
}

4.2. 一对一查询模式(2) 

我们在一对一查询模式(1)的OrderMapper接口方法上做适当调整:

package com.example.mapper;

import com.example.domain.Order;
import com.example.domain.User;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface OrderMapper {

    @Select("select * from `order`")
    @Results({
            @Result(column = "oid", property = "id"),
            @Result(column = "ordertime", property = "orderTime"),
            @Result(column = "total", property = "total"),
            @Result(
                    property = "user", // 要封装的属性名称
                    column = "uid", // 根据这个字段去查询user表的数据
                    javaType = User.class, // 要封装的实体类型
                    // select属性代表查询这个接口的方法获得数据
                    one = @One(select = "com.example.mapper.UserMapper.findById")
            )
    })
    List<Order> findAll();
}

4.3. 一对多查询模型

4.3.1. sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 加载外部properties -->
    <properties resource="jdbc.properties"></properties>

    <settings>
        <!-- 其他配置 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <typeAlias type="com.example.domain.User" alias="user"></typeAlias>
    </typeAliases>

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 指定方言 MySQl -->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
    
    <!-- 数据源环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 加载映射关系 -->
    <mappers>
        <!-- 指定接口所在的包 -->
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

4.3.2. properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=Wangzhexiao

4.3.3. UserMapper

package com.example.mapper;

import com.example.domain.User;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface UserMapper {

    @Select("select * from user")
    @Results({
            @Result(column = "id", property = "id"),
            @Result(column = "username", property = "username"),
            @Result(column = "password", property = "password"),
            @Result(
                    property = "orderList", // 要封装的属性名称
                    column = "id", // 根据这个字段去查询订单表的数据
                    javaType = List.class, // 要封装的实体类型
                    // select属性代表查询这个接口的方法获得数据
                    many = @Many(select = "com.example.mapper.OrderMapper.findByUid")
            )
    })
    List<User> findUserAndOrderAll();
}

4.3.4. OrderMapper

package com.example.mapper;

import com.example.domain.Order;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface OrderMapper {

    @Select("select * from `order` where uid = #{uid}")
    List<Order> findByUid(int uid);
}

4.3.5. Order实体类

package com.example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Order {

    private int id;
    private Date orderTime;
    private double total;
    private User user;
}

4.3.6. User实体类

package com.example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Order {

    private int id;
    private Date orderTime;
    private double total;
    private User user;
}

4.4. 多对多查询模型

4.4.1. sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 加载外部properties -->
    <properties resource="jdbc.properties"></properties>

    <settings>
        <!-- 其他配置 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <typeAlias type="com.example.domain.User" alias="user"></typeAlias>
    </typeAliases>

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 指定方言 MySQl -->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
    
    <!-- 数据源环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 加载映射关系 -->
    <mappers>
        <!-- 指定接口所在的包 -->
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

4.4.2. properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=Wangzhexiao

4.4.3. UserMapper

package com.example.mapper;

import com.example.domain.User;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;

public interface UserMapper {

    @Select("select * from user")
    @Results({
            @Result(column = "id", property = "id"),
            @Result(column = "username", property = "username"),
            @Result(column = "password", property = "password"),
            @Result(
                    property = "roleList", // 要封装的属性名称
                    column = "id", // 根据这个字段去查询角色表的数据
                    javaType = List.class, // 要封装的实体类型
                    // select属性代表查询这个接口的方法获得数据
                    many = @Many(select = "com.example.mapper.RoleMapper.findByUid")
            )
    })
    List<User> findUserAndRoleAll();
}

4.4.4. RoleMapper

package com.example.mapper;

import com.example.domain.Role;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface RoleMapper {
    @Select("select * from user_role ur, role r where ur.role_id = r.id and ur.user_id = #{uid}")
    List<Role> findByUid(int uid);
}

4.4.5. Role实体类

package com.example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Role {
    private int id;
    private String roleName;
    private String roleDesc;
}

4.4.6. User实体类

package com.example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
    private int id;
    private String username;
    private String password;
    private Date birthday;
    // 描述当前用户具有多个角色
    private List<Role> roleList;
}

;