JavaEE Mybatis Mapper使用

1. 開發(fā)規(guī)范

Mapper接口開發(fā)方法只需要程序員編寫Mapper接口(相當(dāng)于Dao接口)霉晕,由Mybatis框架根據(jù)接口定義創(chuàng)建接口的動(dòng)態(tài)代理對(duì)象,代理對(duì)象的方法體同上邊Dao接口實(shí)現(xiàn)類方法。
Mapper接口開發(fā)需要遵循以下規(guī)范:

  • Mapper.xml文件中的namespace與mapper接口的類路徑相同,即namespace必須是接口的全限定名。
  • Mapper接口方法名和Mapper.xml中定義的每個(gè)statement的id相同。
  • Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個(gè)sql的parameterType的類型相同橄镜。
  • Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個(gè)sql的resultType的類型相同。

2. 簡單使用Mapper

本項(xiàng)目數(shù)據(jù)庫基于JavaEE Mybatis使用文章

1). 編寫Mapper接口

在工程的src目錄下新建一個(gè)com.mazaiting.mapper包冯乘,并在該包下創(chuàng)建一個(gè)Mapper接口——UserMapper.java

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

接口定義有如下特點(diǎn):

  • mapper接口方法名和mapper.xml中定義的statement的id相同洽胶。
  • mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的statement的parameterType的類型相同。
  • mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的statement的resultType的類型相同裆馒。
2). 編寫Mapper.xml(映射文件)

在config源碼目錄下新建一個(gè)mapper的普通文件夾姊氓,該文件夾專門用于存放映射文件。然后在該文件夾下創(chuàng)建一個(gè)名為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內(nèi)容如下:

<?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事務(wù)管理 -->
            <transactionManager type="JDBC" />
            <!-- 數(shù)據(jù)庫連接池 -->
            <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>
    
    <!-- 添加的內(nèi)容 -->
    <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. 創(chuàng)建SqlSessionFactoryBuilder對(duì)象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加載配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 創(chuàng)建SqlSessionFactory對(duì)象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetUserById() {
        // 和Spring整合后就省略了
        SqlSession session = factory.openSession();
        // 獲得代理對(duì)象(和Spring整合后只需要通過Spring容器拿到Usermapper接口的搭理對(duì)象就可以了)
        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). 打印結(jié)果:

testGetUserById

圖1.png

testGetUserByName

圖2.png

testAddUser

圖3.png

6). 總結(jié)
  • selectOne和selectList
    動(dòng)態(tài)代理對(duì)象調(diào)用sqlSession.selectOne()和sqlSession.selectList()是根據(jù)mapper接口方法的返回值決定喷好,如果返回list則調(diào)用selectList方法翔横,如果返回單個(gè)對(duì)象則調(diào)用selectOne方法。
  • namespace
    mybatis官方推薦使用mapper代理方法開發(fā)mapper接口梗搅,程序員不用編寫mapper接口實(shí)現(xiàn)類禾唁,使用mapper代理方法時(shí)效览,輸入?yún)?shù)可以使用pojo包裝對(duì)象或map對(duì)象,保證dao的通用性荡短。

3. SqlMapConfig.xml配置文件

1). 配置內(nèi)容

SqlMapConfig.xml文件中配置的內(nèi)容和順序如下:

    1>. properties(屬性)
    2>. settings(全局配置參數(shù))
    3>. typeAliases(類型別名)
    4>. typeHandlers(類型處理器)
    5>. objectFactory(對(duì)象工廠)
    6>. plugins(插件)
    7>. environments(環(huán)境集合屬性對(duì)象) 
        I.environment(環(huán)境子屬性對(duì)象) 
            1>>.transactionManager(事務(wù)管理)
            2>>.dataSource(數(shù)據(jù)源)
    8>. mappers(映射器)
2). properties(屬性)

在SqlMapConfig.xml配置文件中丐枉,我們可把數(shù)據(jù)庫連接信息配置到properties標(biāo)簽當(dāng)中

    <!-- 配置屬性 -->
    <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文件內(nèi)容:

<?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事務(wù)管理 -->
            <transactionManager type="JDBC" />
            <!-- 數(shù)據(jù)庫連接池 -->
            <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>
    
    <!-- 添加的內(nèi)容 -->
    <mappers>
        <!-- resource是基于classpath來查找的 -->
        <mapper resource="sqlmap/user.xml"/>
        <mapper resource="mapper/mapper.xml"/>
    </mappers>
</configuration>

將數(shù)據(jù)庫連接信息配置到一個(gè)java屬性文件中,然后再來引用其中的配置信息肢预。我按照這種指導(dǎo)思想在classpath下定義一個(gè)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文件內(nèi)容:

<?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事務(wù)管理 -->
            <transactionManager type="JDBC" />
            <!-- 數(shù)據(jù)庫連接池 -->
            <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>
    
    <!-- 添加的內(nèi)容 -->
    <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>
        <!-- 單個(gè)定義別名,別名不區(qū)分大小寫 -->
        <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">
    <!-- 應(yīng)用別名 -->
    <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類的別名洼哎,且別名是不區(qū)分大小寫的.

  • 批量定義別名
    <!-- 配置pojo的別名 -->
    <typeAliases>
        <!-- 批量別名定義烫映,掃描包的形式創(chuàng)建別名,別名就是類名噩峦,且不區(qū)分大小寫 -->
        <package name="com.mazaiting.po"/>
    </typeAliases>
4). SqlMapConfig.xml文件加載mapper.xml文件
  • <mapper resource=" " />
    使用相對(duì)于類路徑的資源锭沟,如
<mapper resource="sqlmap/user.xml"/>
圖4.png
  • <mapper class=" " />
    使用mapper接口類路徑,如:
    <mapper class="com.mazaiting.mapper.UserMapper"/>

圖5.png

注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同识补,且放在同一個(gè)目錄中族淮。

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

圖6.png

注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同凭涂,且放在同一個(gè)目錄中祝辣。

4. 輸入映射--parameterType(輸入類型)

1). 傳遞簡單類型
    <select id="getUserById" parameterType="int" resultType="com.mazaiting.po.User">
        select * from user where id = #{id};
    </select>
圖7.png
2). 傳遞pojo對(duì)象

MyBatis使用ognl表達(dá)式解析對(duì)象字段的值鞋怀,#{}或者${}括號(hào)中的值為pojo屬性名稱脊串。

    <insert id="addUser" parameterType="com.mazaiting.po.User">
        insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
圖8.png
3). 傳遞pojo包裝對(duì)象

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. 創(chuàng)建SqlSessionFactoryBuilder對(duì)象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加載配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 創(chuàng)建SqlSessionFactory對(duì)象
        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. 打印結(jié)果:


圖9.png
4). 傳遞HashMap(傳遞HashMap在實(shí)際開發(fā)中用的很少)

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. 創(chuàng)建SqlSessionFactoryBuilder對(duì)象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加載配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 創(chuàng)建SqlSessionFactory對(duì)象
        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. 打印結(jié)果


圖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">
    <!-- 查詢表中的記錄數(shù) -->
    <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. 創(chuàng)建SqlSessionFactoryBuilder對(duì)象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加載配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 創(chuàng)建SqlSessionFactory對(duì)象
        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. 打印結(jié)果:


圖11.png
2). 輸出pojo對(duì)象
    <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>
圖12.png
3). 輸出pojo列表
    <select id="getUserByName" parameterType="string" resultType="com.mazaiting.po.User">
        select * from user where username like '%${value}%'
    </select>
圖13.png
4). 當(dāng)pojo中屬性名和數(shù)據(jù)庫中字段名不相同時(shí)
圖14.png

I. 在com.mazaiting.po包下創(chuàng)建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包下創(chuàng)建接口OrderMapper

public interface OrderMapper {

}

III. 在com.mazaiting.mapper包下創(chuàng)建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. 打印結(jié)果


圖15.png

可以看到userId讀取出來為null,原因 數(shù)據(jù)庫表中的字段名為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>

執(zhí)行測試方法瓢宦,打印結(jié)果:


圖16.png
6). 獲取userId解決辦法2-- resultMap

resultMap可以指定pojo將查詢結(jié)果映射為pojo蟆盹,但需要pojo的屬性名和sql查詢的列名一致方可映射成功垦垂。如果sql查詢字段名和pojo的屬性名不一致痹升,可以通過resultMap將字段名和屬性名作一個(gè)對(duì)應(yīng)關(guān)系 阿迈,resultMap實(shí)質(zhì)上還需要將查詢結(jié)果映射到pojo對(duì)象中攻谁。
resultMap可以實(shí)現(xiàn)將查詢結(jié)果映射為復(fù)雜類型的pojo稚伍,比如在查詢結(jié)果映射對(duì)象中包括pojo和list實(shí)現(xiàn)一對(duì)一查詢和一對(duì)多查詢。

  • type:指resultMap要映射成的數(shù)據(jù)類型(返回結(jié)果映射的pojo戚宦,可以使用別名)个曙。
  • <id />:此屬性表示查詢結(jié)果集的唯一標(biāo)識(shí),非常重要受楼。如果是多個(gè)字段為復(fù)合唯一約束則定義多個(gè)<id />困檩。
  • property:表示Orders類的屬性。
  • column:表示sql查詢出來的字段名那槽。
    column和property放在一塊兒表示將sql查詢出來的字段映射到指定的pojo類屬性上悼沿。
  • <result />:普通列使用result標(biāo)簽映射。

解決辦法:
將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>

執(zhí)行測試并打印:


圖17.png

6. 動(dòng)態(tài)SQL

1). if標(biāo)簽

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要做不等于空字符串的校驗(yàn)。
  • User類中id屬性的類型要改為Integer包裝類型义郑,因?yàn)閕nt類型的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. 創(chuàng)建SqlSessionFactoryBuilder對(duì)象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加載配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 創(chuàng)建SqlSessionFactory對(duì)象
        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. 執(zhí)行測試方法,打印結(jié)果:


圖18.png
2). where標(biāo)簽

可將上個(gè)例子中的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>

執(zhí)行測試代碼,打印結(jié)果:


圖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">
    <!-- 動(dòng)態(tài)sql foreach測試 -->
    <select id="findUserByIds" parameterType="queryvo" resultType="user">
        select * from user
        <where>
            <!-- and id in(1,10,20,21,31)
                collection  遍歷的集合
                item        條目
                open        循環(huán)之前的內(nèi)容
                close       循環(huán)之后的內(nèi)容
                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. 創(chuàng)建SqlSessionFactoryBuilder對(duì)象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加載配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 創(chuàng)建SqlSessionFactory對(duì)象
        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. 測試方法打印結(jié)果:


圖20.png
4). sql片段

sql中可將重復(fù)的sql提取出來非驮,使用時(shí)用include引用即可交汤,最終達(dá)到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片段,則在引用時(shí)需要加上namespace劫笙,如下:
<include refid="namespace.sql片段id"/>

7. 一對(duì)一關(guān)聯(lián)映射

1). 一對(duì)一查詢--方法一

I. 創(chuàng)建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. 打印結(jié)果:

圖21.png

注意:定義專門的po類作為輸出類型,其中定義了sql查詢結(jié)果集所有的字段填大。此方法較為簡單戒洼,企業(yè)中使用普遍。

2). 一對(duì)一查詢--方法二

使用resultMap允华,定義專門的resultMap用于映射一對(duì)一查詢結(jié)果圈浇。首先在Order類中加入user屬性,user屬性中用于存儲(chǔ)關(guān)聯(lián)查詢的用戶信息靴寂,因?yàn)橛唵侮P(guān)聯(lián)查詢用戶是一對(duì)一關(guān)系磷蜀,所以這里使用單個(gè)User對(duì)象存儲(chǔ)關(guān)聯(lián)查詢的用戶信息。
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"/>
        <!-- 配置一對(duì)一關(guān)聯(lián)映射 -->
        <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:表示進(jìn)行關(guān)聯(lián)查詢單條記錄百炬。
  • property:表示關(guān)聯(lián)查詢的結(jié)果存儲(chǔ)在com.mazaiting.po.Order的user屬性中蠕搜。即property對(duì)應(yīng)Orders類里面一對(duì)一關(guān)聯(lián)映射的那個(gè)屬性,即user屬性收壕。
  • javaType:表示關(guān)聯(lián)查詢的結(jié)果類型妓灌。即user屬性的數(shù)據(jù)類型,可使用別名蜜宪。
  • <id property="id" column="user_id"/>:查詢結(jié)果的user_id列對(duì)應(yīng)關(guān)聯(lián)對(duì)象的id屬性虫埂,這里是<id />表示user_id是關(guān)聯(lián)查詢對(duì)象的唯一標(biāo)識(shí)。
  • <result property="username" column="username"/>:查詢結(jié)果的username列對(duì)應(yīng)關(guān)聯(lián)對(duì)象的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. 打印結(jié)果:


圖22.png

總結(jié):使用association完成關(guān)聯(lián)查詢掉伏,將關(guān)聯(lián)查詢信息映射到pojo對(duì)象中。

3). 一對(duì)多關(guān)聯(lián)映射

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"/>
        <!-- 配置一對(duì)多映射 -->
        <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部分定義了用戶關(guān)聯(lián)的訂單信息澳窑。表示關(guān)聯(lián)查詢結(jié)果集斧散。
  • property=”orders”:關(guān)聯(lián)查詢的結(jié)果集存儲(chǔ)在User對(duì)象的哪個(gè)屬性上。即property對(duì)應(yīng)User對(duì)象中的集合屬性摊聋。
  • ofType=”order”:指定關(guān)聯(lián)查詢的結(jié)果集中的對(duì)象類型即List中的對(duì)象類型鸡捐。此處可以使用別名,也可以使用全限定名麻裁。
  • <id />及<result/>的意義同一對(duì)一查詢箍镜。
    III. 在UserMapper接口中添加方法
public interface UserMapper {
    List<User> getUserWithOrders();
}

IV. 測試方法

public class UserMapperTest {
    // 單例工廠
    private SqlSessionFactory factory;
    @Before
    public void init() throws IOException {
        // 1. 創(chuàng)建SqlSessionFactoryBuilder對(duì)象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加載配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 創(chuàng)建SqlSessionFactory對(duì)象
        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. 執(zhí)行測試源祈,打印結(jié)果:


圖23.png

代碼下載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市色迂,隨后出現(xiàn)的幾起案子香缺,更是在濱河造成了極大的恐慌,老刑警劉巖歇僧,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件图张,死亡現(xiàn)場離奇詭異,居然都是意外死亡诈悍,警方通過查閱死者的電腦和手機(jī)祸轮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來写隶,“玉大人倔撞,你說我怎么就攤上這事讲仰∧脚浚” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵鄙陡,是天一觀的道長冕房。 經(jīng)常有香客問我,道長趁矾,這世上最難降的妖魔是什么耙册? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮毫捣,結(jié)果婚禮上详拙,老公的妹妹穿的比我還像新娘。我一直安慰自己蔓同,他們只是感情好饶辙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斑粱,像睡著了一般弃揽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上则北,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天矿微,我揣著相機(jī)與錄音,去河邊找鬼尚揣。 笑死涌矢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的快骗。 我是一名探鬼主播蒿辙,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼拇泛,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了思灌?” 一聲冷哼從身側(cè)響起俺叭,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泰偿,沒想到半個(gè)月后熄守,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耗跛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年裕照,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片调塌。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晋南,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出羔砾,到底是詐尸還是另有隱情负间,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布姜凄,位于F島的核電站政溃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏态秧。R本人自食惡果不足惜董虱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望申鱼。 院中可真熱鬧愤诱,春花似錦、人聲如沸捐友。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楚殿。三九已至撮慨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脆粥,已是汗流浹背砌溺。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留变隔,地道東北人规伐。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像匣缘,于是被迫代替她去往敵國和親猖闪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲜棠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容

  • Java數(shù)據(jù)持久化之mybatis 一. mybatis簡介 1.1 原始的JDBC操作: Java 通過 Jav...
    小Q逛逛閱讀 4,929評(píng)論 0 16
  • 1.1mybatis下載 mybaits 的代碼由github.com 管理,地址:https://github....
    暖熊熊閱讀 862評(píng)論 0 5
  • 非本人總結(jié)的筆記培慌,抄點(diǎn)筆記復(fù)習(xí)復(fù)習(xí)豁陆。感謝傳智博客及黑馬程序猿成長 什么是Mybatis ? MyBatis 本...
    鍵盤瞎閱讀 1,293評(píng)論 0 4
  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL吵护、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,527評(píng)論 0 4
  • 21世紀(jì)才蒞臨不久,互聯(lián)網(wǎng)時(shí)代就尾隨而至瓮恭。電腦主機(jī)們掛著一條光纜尾巴藏進(jìn)千家萬戶雄坪,人人口袋里都能摸出來一只隨時(shí)聯(lián)網(wǎng)...
    框框之上閱讀 441評(píng)論 0 1