JavaEE Mybatis Mapper使用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 1. 开发规范Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

1. 开发规范

Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:

  • Mapper.xml文件中的namespace与mapper接口的类路径相同,即namespace必须是接口的全限定名。
  • Mapper接口方法名和Mapper.xml中定义的每个statement的id相同。
  • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同。
  • Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。

2. 简单使用Mapper

本项目数据库基于JavaEE Mybatis使用文章

1). 编写Mapper接口

在工程的src目录下新建一个com.mazaiting.mapper包,并在该包下创建一个Mapper接口——UserMapper.java

public interface UserMapper {
    User getUserById(int id);
    List<User> getUserByName(String username);
    void addUser(User user);
}

接口定义有如下特点:

  • mapper接口方法名和mapper.xml中定义的statement的id相同。
  • mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同。
  • mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同。
2). 编写Mapper.xml(映射文件)

在config源码目录下新建一个mapper的普通文件夹,该文件夹专门用于存放映射文件。然后在该文件夹下创建一个名为mapper.xml的映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    <select id="getUserById" parameterType="int" resultType="com.mazaiting.po.User">
        select * from user where id = #{id}
    </select>
    
    <select id="getUserByName" parameterType="string" resultType="com.mazaiting.po.User">
        select * from user where username like '%${value}%'
    </select>
    
    <insert id="addUser" parameterType="com.mazaiting.po.User">
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            select LAST_INSERT_ID() 
        </selectKey>
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
</mapper>
3). 加载mapper.xml映射文件

在SqlMapConfig.xml文件添加如下配置:

<mapper resource="mapper/mapper.xml"/>

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>
    <!-- 和spring整合后environments配置将废除 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    
    <!-- 添加的内容 -->
    <mappers>
        <!-- resource是基于classpath来查找的 -->
        <mapper resource="sqlmap/user.xml"/>
        <mapper resource="mapper/mapper.xml"/>
    </mappers>
</configuration>
4). 编写测试程序
public class UserMapperTest {
    // 单例工厂
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetUserById() {
        // 和Spring整合后就省略了
        SqlSession session = factory.openSession();
        // 获得代理对象(和Spring整合后只需要通过Spring容器拿到Usermapper接口的搭理对象就可以了)
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = userMapper.getUserById(10);
        System.out.println(user);
        // 和Spring整合后就省略了
        session.close();
    }
    
    @Test
    public void testGetUserByName() {
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> list = mapper.getUserByName("张");
        for(User user : list) {
            System.out.println(user);
        }
        session.close();
    }
    
    @Test
    public void testAddUser(){
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("凌浩雨");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("理化所");
        mapper.addUser(user);
        System.out.println(user.getId());
        session.commit();
        session.close();
    }
    
}
5). 打印结果:

testGetUserById

img_b6ef3e9d2ffbe89dec3018fbdb86dcd3.png
图1.png

testGetUserByName

img_dcb7bda47eca2da061e8cbed49587d31.png
图2.png

testAddUser

img_6cac28e3aced33fa30b6a7a47de058fd.png
图3.png

6). 总结
  • selectOne和selectList
    动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。
  • namespace
    mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

3. SqlMapConfig.xml配置文件

1). 配置内容

SqlMapConfig.xml文件中配置的内容和顺序如下:

    1>. properties(属性)
    2>. settings(全局配置参数)
    3>. typeAliases(类型别名)
    4>. typeHandlers(类型处理器)
    5>. objectFactory(对象工厂)
    6>. plugins(插件)
    7>. environments(环境集合属性对象) 
        I.environment(环境子属性对象) 
            1>>.transactionManager(事务管理)
            2>>.dataSource(数据源)
    8>. mappers(映射器)
2). properties(属性)

在SqlMapConfig.xml配置文件中,我们可把数据库连接信息配置到properties标签当中

    <!-- 配置属性 -->
    <properties>
        <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
    </properties>

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>
        <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
    </properties>


    <!-- 和spring整合后environments配置将废除 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    
    <!-- 添加的内容 -->
    <mappers>
        <!-- resource是基于classpath来查找的 -->
        <mapper resource="sqlmap/user.xml"/>
        <mapper resource="mapper/mapper.xml"/>
    </mappers>
</configuration>

将数据库连接信息配置到一个java属性文件中,然后再来引用其中的配置信息。我按照这种指导思想在classpath下定义一个db.properties文件.
db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

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="db.properties">
        <!-- <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/> -->
        <property name="jdbc.driver" value="${jdbc.driver}"/>
        <property name="jdbc.url" value="${jdbc.url}"/>
    </properties>


    <!-- 和spring整合后environments配置将废除 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <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>
        <!-- resource是基于classpath来查找的 -->
        <mapper resource="sqlmap/user.xml"/>
        <mapper resource="mapper/mapper.xml"/>
    </mappers>
</configuration>
3). typeAliases(类型别名)
  • mybatis支持别名
别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
map Map
  • 自定义别名
    在SqlMapConfig.xml文件中添加:
    <!-- 配置pojo的别名 -->
    <typeAliases>
        <!-- 单个定义别名,别名不区分大小写 -->
        <typeAlias type="com.mazaiting.po.User" alias="User"/>
    </typeAliases>

则mapper.xml文件可以修改为:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    <!-- 应用别名 -->
    <select id="getUserById" parameterType="int" resultType="User">
        select * from user where id = #{id}
    </select>
    
    <select id="getUserByName" parameterType="string" resultType="com.mazaiting.po.User">
        select * from user where username like '%${value}%'
    </select>
    
    <insert id="addUser" parameterType="com.mazaiting.po.User">
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            select LAST_INSERT_ID() 
        </selectKey>
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
</mapper>

注意:resultType属性的值就是User类的别名,且别名是不区分大小写的.

  • 批量定义别名
    <!-- 配置pojo的别名 -->
    <typeAliases>
        <!-- 批量别名定义,扫描包的形式创建别名,别名就是类名,且不区分大小写 -->
        <package name="com.mazaiting.po"/>
    </typeAliases>
4). SqlMapConfig.xml文件加载mapper.xml文件
  • <mapper resource=" " />
    使用相对于类路径的资源,如
<mapper resource="sqlmap/user.xml"/>
img_a80e48c2f89599d83b96c2d9b87cd94a.png
图4.png
  • <mapper class=" " />
    使用mapper接口类路径,如:
    <mapper class="com.mazaiting.mapper.UserMapper"/>

img_fb8261e264660b5beb3be7a9f22e8090.png
图5.png

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

  • <package name=""/>
    注册指定包下的所有mapper接口,如:
    <package name="com.mazaiting.mapper"/>

img_b2d5c4fcdd7d338414f0f2de2919ef0e.png
图6.png

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

4. 输入映射--parameterType(输入类型)

1). 传递简单类型
    <select id="getUserById" parameterType="int" resultType="com.mazaiting.po.User">
        select * from user where id = #{id};
    </select>
img_1e2df6611e488b88cd24250efe3a83a6.png
图7.png
2). 传递pojo对象

MyBatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。

    <insert id="addUser" parameterType="com.mazaiting.po.User">
        insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
img_294b6a43dd62f34ee3a0d11c9a91ab75.png
图8.png
3). 传递pojo包装对象

I. 在com.mazaiting.po包下新建QueryVo类

public class QueryVo {
    private User user;
    public void setUser(User user) {
        this.user = user;
    }
    public User getUser() {
        return user;
    }
}

II. 在UserMapper.xml文件中添加查询语句

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    
    <select id="getUserByQueryVo" parameterType="queryvo" resultType="user">
        select * from user where id = #{user.id}    
    </select>
    
</mapper>

III. 在UserMapper接口中添加方法

public interface UserMapper {
    User getUserByQueryVo(QueryVo queryVo);
}

IV. 编写测试代码

public class UserMapperTest {
    // 单例工厂
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test 
    public void testGetUserByQueryVo(){
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        QueryVo queryVo = new QueryVo();
        User user = new User();
        user.setId(10);
        queryVo.setUser(user);
        User queryUser = mapper.getUserByQueryVo(queryVo);
        System.out.println(queryUser);
        session.close();
    }
}

V. 打印结果:


img_8c58f305a2d0830e50341870163d183e.png
图9.png
4). 传递HashMap(传递HashMap在实际开发中用的很少)

I. 在UserMapper中添加查询方法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    <!-- 传递HashMap综合查询用户信息 -->
    <select id="findUserByHashMap" parameterType="hashmap" resultType="user">
        select * from user where id = #{id} and username like '%${username}%'
    </select>
</mapper>

注:id和username是HashMap的key。
II. 在UserMapper中添加接口方法

public interface UserMapper {
    User findUserByHashMap(HashMap<String, Object> map);
}

III. 编写测试方法

public class UserMapperTest {
    // 单例工厂
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testFindUserByHashMap(){
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("id", 10);
        map.put("username", "张");
        User user = mapper.findUserByHashMap(map);
        System.out.println(user);
        session.close();
    }
}

IV. 打印结果


img_7932bd009d517dabc6ff85e47ec03fa2.png
图10.png

5. 输出映射--resultType(输出类型)

1). 输出简单类型

I. 在UserMapper.xml文件中添加配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    <!-- 查询表中的记录数 -->
    <select id="getUserCount" resultType="int">
        select COUNT(*) from user
    </select>
</mapper>

II. 在UserMapper接口中添加方法

public interface UserMapper {
    Integer getUserCount();
}

III. 编写测试方法

public class UserMapperTest {
    // 单例工厂
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetUserCount(){
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        int count = mapper.getUserCount();
        System.out.println("共有 " + count + "条记录");
        session.close();
    }
}

IV. 打印结果:


img_e07e9dae67b37a71ad2da3d396f3a061.png
图11.png
2). 输出pojo对象
    <insert id="addUser" parameterType="com.mazaiting.po.User">
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            select LAST_INSERT_ID() 
        </selectKey>
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
img_f1410095dec8ace683ff1564fdea21e9.png
图12.png
3). 输出pojo列表
    <select id="getUserByName" parameterType="string" resultType="com.mazaiting.po.User">
        select * from user where username like '%${value}%'
    </select>
img_fb4c557afa7f52bfa4a5d83c23b8309a.png
图13.png
4). 当pojo中属性名和数据库中字段名不相同时
img_e021d48d4cc8cfeaae7a57ccd64bd0ee.png
图14.png

I. 在com.mazaiting.po包下创建Order.java

public class Order {
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
    @Override
    public String toString() {
        return "Order [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
                + ", note=" + note + "]";
    }
    
}

II. 在com.mazaiting.mapper包下创建接口OrderMapper

public interface OrderMapper {

}

III. 在com.mazaiting.mapper包下创建OrderMapper.xml文件

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

    <select id="getOrderList" resultType="order">
        select * from order 
    </select>   
    
</mapper>

IV. 在OrderMapper接口中添加方法

public interface OrderMapper {
    List<Order> getOrderList();
}

V. 编写测试方法

public class OrderMapperTest {
    SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetOrderList() {
        SqlSession session = factory.openSession();
        OrderMapper mapper = session.getMapper(OrderMapper.class);
        List<Order> list = mapper.getOrderList();
        for (Order order : list) {
            System.out.println(order);
        }
        session.close();
    }
}

VI. 打印结果


img_96c25875e3ae40bfd04e2dfd489b925b.png
图15.png

可以看到userId读取出来为null,原因 数据库表中的字段名为user_id.

5). 获取userId解决办法1

将OrderMapper.xml文件中的

    <select id="getOrderList" resultType="order">
        select * from order 
    </select>

修改为

    <select id="getOrderList" resultType="order">
        select id,user_id userId,number,createtime,note from orders
    </select>

执行测试方法,打印结果:


img_5890287d267c4032fec2de2c8e16f3bf.png
图16.png
6). 获取userId解决办法2-- resultMap

resultMap可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

  • type:指resultMap要映射成的数据类型(返回结果映射的pojo,可以使用别名)。
  • <id />:此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个<id />。
  • property:表示Orders类的属性。
  • column:表示sql查询出来的字段名。
    column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。
  • <result />:普通列使用result标签映射。

解决办法:
将OrderMapper.xml文件中的

    <select id="getOrderList" resultType="order">
        select * from order 
    </select>

修改为

    <resultMap type="order" id="order_list_result_map">
        <!-- id是主键的映射,其中property是pojo中主键的属性,column是返回主键的列 -->
        <id property="id" column="id"/>
        <!-- 普通列使用result映射 -->
        <result property="userId" column="user_id"/>
        <result property="number" column="number"/>
        <result property="createtime" column="createtime"/>
        <result property="note" column="note"/>
    </resultMap>
    <!-- 使用resultMap方式 -->
    <select id="getOrderList" resultMap="order_list_result_map">
        select * from orders
    </select>

执行测试并打印:


img_a8c68624229c70eb4b7e9d95e6223704.png
图17.png

6. 动态SQL

1). if标签

I. 在UserMapper.xml添加方法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    <select id="findUserList" parameterType="user" resultType="user">
        select * from user
        where 1=1 
        <if test="id!=null">
            and id = #{id}
        </if>   
        <if test="username!=null and username !=''">
            and username like '%${username}%'
        </if>
    </select>
</mapper>

注意:

  • username要做不等于空字符串的校验。
  • User类中id属性的类型要改为Integer包装类型,因为int类型的id是不可能为null的!

II. 在UserMapper中添加方法

public interface UserMapper {
    List<User> findUserList(User user);
}

III. 测试方法

public class UserMapperTest {
    // 单例工厂
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testFindUserList(){
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setId(10);
        List<User> list = mapper.findUserList(user);
        for (User nUser : list) {
            System.out.println(nUser);
        }
        session.close();
    }
}

IV. 执行测试方法,打印结果:


img_345f6b09a46f1b4f65f1eee9d54f8a29.png
图18.png
2). where标签

可将上个例子中的UserMapper.xml文件中

    <select id="findUserList" parameterType="user" resultType="user">
        select * from user
        where 1=1 
        <if test="id!=null">
            and id = #{id}
        </if>   
        <if test="username!=null and username !=''">
            and username like '%${username}%'
        </if>
    </select>

修改为:

    <select id="findUserList" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="id!=null">
                and id = #{id}
            </if>
            <if test="username!=null and username !=''">
                and username like '%${username}%'
            </if>
        </where>
    </select>

执行测试代码,打印结果:


img_ca4aef846e9a76591d9d2bce58656925.png
图19.png
3). foreach

I. 在QueryVo类中添加id列表属性

public class QueryVo {
    private User user;
    private List<Integer> ids;
    public void setUser(User user) {
        this.user = user;
    }
    public User getUser() {
        return user;
    }
    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
    public List<Integer> getIds() {
        return ids;
    }
}

II. 在UserMapper.xml文件中添加查询

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    <!-- 动态sql foreach测试 -->
    <select id="findUserByIds" parameterType="queryvo" resultType="user">
        select * from user
        <where>
            <!-- and id in(1,10,20,21,31)
                collection  遍历的集合
                item        条目
                open        循环之前的内容
                close       循环之后的内容
                separator   分隔符
             -->
            <foreach collection="ids" item="id" open="and id in(" close=")" separator=",">
                #{id}
            </foreach>
        </where>
    </select>
</mapper>

III. 在UserMapper接口中添加方法

public interface UserMapper {
    List<User> findUserByIds(QueryVo queryVo);
}

IV. 测试方法

public class UserMapperTest {
    // 单例工厂
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testFindUserByIds(){
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        QueryVo queryVo = new QueryVo();
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(10);
        list.add(16);
        list.add(22);
        queryVo.setIds(list);
        List<User> userList = mapper.findUserByIds(queryVo);
        for (User user : userList) {
            System.out.println(user);
        }
        session.close();
    }
}

V. 测试方法打印结果:


img_ce345ec863bc4c8a28e783d9d3aaf4d6.png
图20.png
4). sql片段

sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的
将下面的select方法使用sql片段:

    <select id="findUserList" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="id!=null">
                and id = #{id}
            </if>
            <if test="username!=null and username !=''">
                and username like '%${username}%'
            </if>
        </where>
    </select>

修改为:

    <!-- 查询字段 -->
    <sql id="user_field_list">
        id,username,birthday,sex,address
    </sql>
    <!-- 抽取where条件 -->
    <sql id="find_user_list_where">
        <where>
            <if test="id!=null">
                and id = #{id}
            </if>
            <if test="username!=null and username !=''">
                and username like '%${username}%'
            </if>
        </where>
    </sql>
    
    <select id="findUserList" parameterType="user" resultType="user">
        select <include refid="user_field_list"/> from user
        <include refid="find_user_list_where"/>
    </select>
5).注意:如果引用其它mapper.xml映射文件的sql片段,则在引用时需要加上namespace,如下:
<include refid="namespace.sql片段id"/>

7. 一对一关联映射

1). 一对一查询--方法一

I. 创建OrderUser类,并继承Order类

public class OrderUser extends Order{
    private String username;
    private String address;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "OrderUser [username=" + username + ", address=" + address + ", getId()=" + getId() + ", getUserId()="
                + getUserId() + ", getNumber()=" + getNumber() + ", getCreatetime()=" + getCreatetime() + ", getNote()="
                + getNote();
    }
}

II. 在OrderMapper.xml文件中添加查询方法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.OrderMapper">
    
    <select id="getOrderUserList" resultType="orderuser">
        select 
            o.id,
            o.user_id userId,
            o.number,
            o.createtime,
            o.note,
            u.username,
            u.address
        from
            orders o
        left join user u on o.user_id = u.id
    </select>

</mapper>

III. 在OrderMapper中添加方法

public interface OrderMapper {
    List<OrderUser> getOrderUserList();
}

IV. 测试方法

public class OrderMapperTest {
    SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetOrderUserList(){
        SqlSession session = factory.openSession();
        OrderMapper mapper = session.getMapper(OrderMapper.class);
        List<OrderUser> list = mapper.getOrderUserList();
        for (OrderUser orderUser : list) {
            System.out.println(orderUser.toString());
        }
        session.close();
    }
}

V. 打印结果:

img_983c28b65e9f84ff84cc6c6e6af35d30.png
图21.png

注意:定义专门的po类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。

2). 一对一查询--方法二

使用resultMap,定义专门的resultMap用于映射一对一查询结果。首先在Order类中加入user属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
I. 修改Order类:

public class Order {
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    private User user;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }
    
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "Order [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
                + ", note=" + note + ", user=" + user + "]";
    }
}

II. 在OrderMapper.xml文件中添加查询方法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.OrderMapper">
    <resultMap type="order" id="order_user_resultmap">
        <id property="id" column="id"/>
        <result property="userId" column="user_id"/>
        <result property="number" column="number"/>
        <result property="createtime" column="createtime"/>
        <result property="note" column="note"/>
        <!-- 配置一对一关联映射 -->
        <association property="user" javaType="com.mazaiting.po.User">
            <id property="id" column="user_id"/>
            <result property="username" column="username"/>
            <result property="address" column="address"/>
        </association>
    </resultMap>

    <select id="getOrderUserResultMap" resultMap="order_user_resultmap">
        select
            o.id,
            o.user_id,
            o.number,
            o.createtime,
            o.note,
            u.username,
            u.address
        from
            orders o
        left join user u on o.user_id = u.id
    </select>

</mapper>
  • association:表示进行关联查询单条记录。
  • property:表示关联查询的结果存储在com.mazaiting.po.Order的user属性中。即property对应Orders类里面一对一关联映射的那个属性,即user属性。
  • javaType:表示关联查询的结果类型。即user属性的数据类型,可使用别名。
  • <id property="id" column="user_id"/>:查询结果的user_id列对应关联对象的id属性,这里是<id />表示user_id是关联查询对象的唯一标识。
  • <result property="username" column="username"/>:查询结果的username列对应关联对象的username属性。

III. 在OrderMapper接口中完成方法

public interface OrderMapper {
    List<Order> getOrderUserResultMap();
}

IV. 测试方法

public class OrderMapperTest {
    SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetOrderUserResultMap(){
        SqlSession session = factory.openSession();
        OrderMapper mapper = session.getMapper(OrderMapper.class);
        List<Order> list = mapper.getOrderUserResultMap();
        for (Order order : list) {
            System.out.println(order.toString());
        }
        session.close();
    }
}

V. 打印结果:


img_a99ee141eec1cb50a200e7b120b8d40f.png
图22.png

总结:使用association完成关联查询,将关联查询信息映射到pojo对象中。

3). 一对多关联映射

I. 在User类中加入List<Orders> orders属性

public class User {
    // id
    private int id;
    // 用户名
    private String username;
    // 性别
    private String sex;
    // 用户名
    private Date birthday;
    // 地址
    private String address;
    private List<Order> orders;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public List<Order> getOrders() {
        return orders;
    }
    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
                + address + ", orders=" + orders + "]";
    }   
}

II. 在UserMapper.xml文件中添加查询方法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mazaiting.mapper.UserMapper">
    <resultMap type="user" id="user_order_resultmap">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <!-- 配置一对多映射 -->
        <collection property="orders" ofType="order">
            <id property="id" column="oid"/>
            <result property="number" column="number"/>
            <result property="createtime" column="createtime"/>
            <result property="note" column="note"/>
        </collection>
    </resultMap>
    
    <select id="getUserWithOrders" resultMap="user_order_resultmap">
        select
            u.id,
            u.username,
            u.birthday,
            u.sex,
            u.address,
            o.id oid,
            o.number,
            o.createtime,
            o.note
        from
            user u
        left join orders o on u.id = o.user_id
    </select>
</mapper>
  • collection部分定义了用户关联的订单信息。表示关联查询结果集。
  • property=”orders”:关联查询的结果集存储在User对象的哪个属性上。即property对应User对象中的集合属性。
  • ofType=”order”:指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
  • <id />及<result/>的意义同一对一查询。
    III. 在UserMapper接口中添加方法
public interface UserMapper {
    List<User> getUserWithOrders();
}

IV. 测试方法

public class UserMapperTest {
    // 单例工厂
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetUserWithOrders(){
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> list =mapper.getUserWithOrders();
        for (User user : list) {
            System.out.println(user.toString());
        }
        session.close();
    }
        
}

V. 执行测试,打印结果:


img_2c35449815b1466f4a182d4930a5f304.png
图23.png

代码下载

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
5月前
|
SQL XML Java
mybatis Mapper的概念与实战
MyBatis 是一个流行的 Java 持久层框架,它提供了对象关系映射(ORM)的功能,使得Java对象和数据库中的表之间的映射变得简单。在MyBatis中,Mapper是一个核心的概念,它定义了映射到数据库操作的接口。简而言之,Mapper 是一个接口,MyBatis 通过这个接口与XML映射文件或者注解绑定,以实现对数据库的操作。
151 1
|
5月前
|
SQL XML Java
|
2月前
|
SQL Java 数据库连接
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
文章讲述了在使用Mybatis时遇到的资源文件找不到的问题,并提供了通过修改Maven配置来解决资源文件编译到target目录下的方法。
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
|
1月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
31 1
|
2月前
|
XML Java 数据库连接
Mybatis 模块拆份带来的 Mapper 扫描问题
Mybatis 模块拆份带来的 Mapper 扫描问题
33 0
|
3月前
|
SQL
自定义SQL,可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,如何自定义SQL呢?利用MyBatisPlus的Wrapper来构建Wh,在mapper方法参数中用Param注
自定义SQL,可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,如何自定义SQL呢?利用MyBatisPlus的Wrapper来构建Wh,在mapper方法参数中用Param注
|
3月前
|
Java 数据库连接 Maven
Private method ‘getVideoList()‘ is never used,mybatis必须指定Mapper文件和实体目录,在参考其他人写的代码,要认真分析别人的代码,不要丢失
Private method ‘getVideoList()‘ is never used,mybatis必须指定Mapper文件和实体目录,在参考其他人写的代码,要认真分析别人的代码,不要丢失
|
4月前
|
SQL Java 数据库连接
Mybatis如何使用mapper代理开发
Mybatis如何使用mapper代理开发
|
4月前
|
XML 关系型数据库 数据库
使用mybatis-generator插件生成postgresql数据库model、mapper、xml
使用mybatis-generator插件生成postgresql数据库model、mapper、xml
343 0
|
4月前
|
SQL Java 数据库连接
Mybatis中一对多mapper配置
Mybatis中一对多mapper配置