美文网首页
Mybatis的映射文件

Mybatis的映射文件

作者: topshi | 来源:发表于2019-05-03 18:08 被阅读0次

一、增删改查

  • BookMapper接口
public interface BookMapper {
    public Book getBookById(Integer id);
    public void addBook(Book book);
    public void updateBook(Book book);
    public void deleteBookById(Integer id);
}
  • BookMapper.xml映射文件
<mapper namespace="dao.BookMapper">  接口路径
    <select id="getBookById" resultType="bean.Book">   id为接口的方法名
        SELECT * FROM RUNOOB_TBL WHERE runoob_id = #{id}
    </select>
    <insert id="addBook" parameterType="bean.Book">
        INSERT INTO RUNOOB_TBL (runoob_title,runoob_author,submission_date)
        VALUES (#{runoobTitle},#{runoobAuthor},#{submissionDate})
    </insert>
    <update id="updateBook" parameterType="bean.Book">
        UPDATE RUNOOB_TBL SET runoob_title = 
        #{runoobTitle},runoob_author = #{runoobAuthor},
        submission_date = #{submissionDate} WHERE runoob_id = #{runoobId}
    </update>
    <delete id="deleteBookById">
        DELETE FROM RUNOOB_TBL WHERE runoob_id = #{id}
    </delete>
</mapper>

二、获取自增主键的值

<insert id="addBook" parameterType="bean.Book" 
                              useGeneratedKeys="true" keyProperty="runoobId">
    INSERT INTO RUNOOB_TBL (runoob_title,runoob_author,submission_date)
    VALUES (#{runoobTitle},#{runoobAuthor},#{submissionDate})
</insert>

添加两个属性:useGeneratedKeys="true" keyProperty="runoobId"keyProperty = "runoobId" 是指定bean的自增主键属性)

三、参数处理

  • 单个参数
    • 单个参数mybatis不会做特殊处理,直接#{参数名}取值
  • 多个参数
    • 多个参数mybatis会将其封装成一个map
    • key:param1,...,paramN,或者参数的索引
    • value:传入的参数值

#{}就是从map中获取指定的key的值

多参数:通过id和author参数来查询book

//接口方法
Book getBookByIdAndAuthor(Integer id,String author);
//mapper
<select id="getBookByIdAndAuthor" resultType="bean.Book">
    SELECT * FROM RUNOOB_TBL WHERE runoob_id = #{id} AND runoob_author = #{author}
</select>

产生异常

Parameter 'id' not found.
Available parameters are [arg1, arg0, param1, param2]

找不到id参数,因为默认map封装的参数是param1...paramN
因此要想这样写runoob_id = #{id} AND runoob_author = #{author},需要命名参数:在封装map对象时指定key
使用注解明确指定参数的键值

Book getBookByIdAndAuthor(@Param("id") Integer id,@Param("author") String author);
  • POJO
    如果多个参数正好是业务逻辑的数据模型,可以直接传入pojo
    • #{属性名}:取出传入的pojo的属性值
  • Map
    如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,可以传入map
    • #{key}:取出map中对应的值
//接口方法
Book getBookByMap(HashMap<String,Object> map);
<!--mapper-->
 <select id="getBookByMap" resultType="bean.Book">
        SELECT * FROM RUNOOB_TBL WHERE runoob_id = #{id} AND 
                            runoob_author = #{author}
    </select>
/**
 * 测试通过map中的Id和author查询数据
 */
HashMap<String,Object> map = new HashMap<String, Object>();
map.put("id",13);
map.put("author","shi");
Book selectBookByMap = mapper.getBookByMap(map);
  • #和$的取值区别
    • #{}:可以获取map中的值或者pojo对象属性的值;
    • ${}:可以获取map中的值或者pojo对象属性的值;

区别:
#{} 是以预编译的形式,将参数设置到sql语句中,PreparedStatement;
${} 取出的值直接拼接在sql语句中,会有安全问题;
大多情况下,我们取参数的值都应该去使用#{}
原生jdbc不支持占位符的地方可以使用${}进行取值
比如分表、排序:财务表按照年份分表拆分
  select * from ${year}_salary where xxx;
  select * from tbl_employee order by ${f_name} ${order}

四、select返回List和Map集合

通过author模糊查询,返回List集合

//定义一个返回List集合的查询方法
List<Book> getBookByAuthorLike(String author);
<!--mapper-->
<!-- 返回的结果是一个集合,但是returnType是集合中的元素类型 -->
<select id="getBookByAuthorLike" resultType="bean.Book">
    SELECT * FROM RUNOOB_TBL WHERE runoob_author LIKE #{author}
</select>
/**
 * 测试按照author模糊查询
 */
List<Book> bookByAuthorLike = mapper.getBookByAuthorLike("%x%");
System.out.println("bookByAuthorLike");
for (Book b:bookByAuthorLike) {
    System.out.println(b);
}
>> 结果
Book{runoobId=2, runoobTitle='python', runoobAuthor='sxc',
                 submissionDate=Wed Jan 02 00:00:00 CST 2019}
Book{runoobId=3, runoobTitle='c', runoobAuthor='sxc',
                 submissionDate=Tue Jan 08 00:00:00 CST 2019}
Book{runoobId=4, runoobTitle='matlab', runoobAuthor='sxc',
                 submissionDate=Thu Jan 03 00:00:00 CST 2019}

通过id查询数据,数据封装成map对象,键是列名,值是对象的值,只返回一条数据

//返回值自动封装成Map对象,键是列名,值是查询到的值
Map<String,Object> getBookByIdReturnMap(Integer id);
<!-- mapper -->
<select id="getBookByIdReturnMap" resultType="map">
    SELECT * FROM RUNOOB_TBL WHERE runoob_id = #{id}
</select>

/**
 * 测试通过Id查询,返回值封装成map对象
 */
Map<String, Object> bookByIdReturnMap = mapper.getBookByIdReturnMap(2);
System.out.println("bookByIdReturnMap");
System.out.println(bookByIdReturnMap);
>> 结果
{runoob_title=python, runoob_author=sxc, 
            submission_date=2019-01-02, runoob_id=2}

通过author模糊查询,结果封装成map对象,键是主键,值是Bean对象,和上面例子不同的是这个是返回多条数据的

/**
 * 查询到一组结果,将结果封装成Map对象,键是主键id,值是查询到的值,需要指定map的键属性, 
 * 用@MapKey注解指定bean的哪个属性作为map的键
 */
@MapKey("runoob_id")  //这种写法是错误的,指定的主键是bean的属性,runoobId
Map<String,Book> getBookByAuthorLikeReturnMap(String author);
报错:
There is no getter for property named 'runoob_id' in 'class bean.Book'

<!-- mapper -->
<select id="getBookByAuthorLikeReturnMap" resultType="bean.Book">
    SELECT * FROM RUNOOB_TBL WHERE runoob_author LIKE #{author}
</select>
/**
 * 测试按照author模糊查询,结果封装成map
 */
Map<String, Book> bookByAuthorLikeReturnMap = 
                                mapper.getBookByAuthorLikeReturnMap("%x%");
System.out.println("bookByAuthorLikeReturnMap");
System.out.println(bookByAuthorLikeReturnMap);
>> 结果
{2=Book{runoobId=2, runoobTitle='python', runoobAuthor='sxc',
               submissionDate=Wed Jan 02 00:00:00 CST 2019}, 
3=Book{runoobId=3, runoobTitle='c', runoobAuthor='sxc', 
               submissionDate=Tue Jan 08 00:00:00 CST 2019}, 
4=Book{runoobId=4, runoobTitle='matlab', runoobAuthor='sxc', 
               submissionDate=Thu Jan 03 00:00:00 CST 2019}}

五、resultMap 自定义结果集的封装规则

resultType属于自动封装的,bean的属性要么和数据库的列名一样,要么使用驼峰命名法,而resultMap可以建立数据库查询返回列名和bean类的属性映射。

//接口方法
Book getBookByIdCustomMap(Integer id);

resultMap的id是它的唯一标识,用于给在下面的select标签引用
自定义数据库查询返回的列名和bean属性的映射规则
<resultMap id="MyBook" type="bean.Book">
    <id column="runoob_id" property="runoobId"/>
    <result column="runoob_title" property="runoobTitle"/>
    <result column="runoob_author" property="runoobAuthor"/>
    <result column="submission_date" property="submissionDate"/>
</resultMap>
<!-- mapper -->
<select id="getBookByIdCustomMap" resultMap="MyBook">
    SELECT * FROM RUNOOB_TBL WHERE runoob_id = #{id}
</select>
/**
 * 测试自定义封装map,resultMap
 */
Book bookByIdCustomMap = mapper.getBookByIdCustomMap(2);
System.out.println("bookByIdCustomMap");
System.out.println(bookByIdCustomMap);
>> 结果
Book{runoobId=2, runoobTitle='python', runoobAuthor='sxc',
 submissionDate=Wed Jan 02 00:00:00 CST 2019}

六、关联查询-级联属性封装结果

增加一张表用于记录runoob_tbl表中书目的store

为Store创建一个bean类,Book的bean变成

public class Book {
    private Integer runoobId;
    private String runoobTitle;
    private String runoobAuthor;
    private Date submissionDate;
    private Store store;

public class Store {
    private Integer id;
    private String storeName;
  • 直接使用resultMap定义封装规则
<!--多表联查结果集封装-->
<resultMap id="myBookStore" type="bean.Book">
    <id column="runoob_id" property="runoobId"/>
    <result column="runoob_title" property="runoobTitle"/>
    <result column="runoob_author" property="runoobAuthor"/>
    <result column="submission_date" property="submissionDate"/>
    <result column="store_id" property="store.id"/>
    <result column="store_name" property="store.storeName"/>
</resultMap>
<select id="getBookAndStore" resultMap="myBookStore">
    SELECT runoob_id,runoob_title,runoob_author,submission_date,store_id,store_name
    FROM runoob_tbl r LEFT JOIN store_tbl s 
    ON r.store_id = s.id WHERE r.runoob_id = #{id}
</select>

两表联查,自定义返回结果的封装规则,column是对应返回的列,property对应待封装对象的各个属性

  • 使用association标签
    association可以指定联合的javabean对象
    property = "store" 指定哪个属性是联合的对象
    javaType:指定这个属性对象的类型(不能省略)
<!--多表联查结果集封装-->
<resultMap id="myBookStore" type="bean.Book">
    <id column="runoob_id" property="runoobId"/>
    <result column="runoob_title" property="runoobTitle"/>
    <result column="runoob_author" property="runoobAuthor"/>
    <result column="submission_date" property="submissionDate"/>
    <!--<result column="store_id" property="store.id"/>-->
    <!--<result column="store_name" property="store.storeName"/>-->
    <!--2.使用association-->
    <association property="store" javaType="bean.Store">
        <id column="store_id" property="id"/>
        <result column="store_name" property="storeName"/>
    </association>
</resultMap>
  • 通过分步查询来查得结果
    先根据id查到Book,使用该Book结果的store_id去store_tbl表查询store_name
    要查store_tbl表的话,需要完成StoreMapper.xml和StoreMapper接口,不多累赘
<!--分步查询查出Book
    先查runoob_tbl表得到store_id,再根据store_id去查store_tbl表的store_name
-->
<resultMap id="myBookByStep" type="bean.Book">
    <id column="runoob_id" property="runoobId"/>
    <result column="runoob_title" property="runoobTitle"/>
    <result column="runoob_author" property="runoobAuthor"/>
    <result column="submission_date" property="submissionDate"/>
    <!--association 定义关联对象的封装规则
        property:关联对象
        select:指定关联属性是通过指定的方法查询得到的
        column: 指定哪一列是select指定方法的传入参数
    -->
    <!--第二步-->
    <association property="store" select="dao.StoreMapper.getStoreById" 
                                                       column="store_id">
        <id column="id" property="id"/>
        <result column="store_name" property="storeName"/>
    </association>
</resultMap>
<!--第一步是通过id查runoob_tbl表,这样就得到用于查store_tbl表的id了-->
<select id="getBookAndStoreByIdStep" resultMap="myBookByStep">
    SELECT * FROM runoob_tbl WHERE runoob_id = #{id}
</select>

分步查询的基础上,实现延时加载,只需要添加两个设置。延时加载意思是说在用到的时候才查询,不用到就不查询了。

<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>

七、collection关联集合封装规则

先看下store的bean对象

public class Store {
    private Integer id;
    private String storeName;
    private List<Book> books;

查询数据,封装到bean的各个属性, books是一个Collection集合

  • 使用collection标签
<resultMap id="getBooks" type="bean.Store">
    <id column="id" property="id"/>
    <result column="store_name" property="storeName"/>
    <!--collection 指定关联集合属性的封装规则
        property:指定封装的bean的collection属性
        ofType:collection容器的内容的属性
    -->
    <collection property="books" ofType="bean.Book">
        <id column="runoob_id" property="runoobId"/>
        <result column="runoob_title" property="runoobTitle"/>
        <result column="runoob_author" property="runoobAuthor"/>
        <result column="submission_date" property="submissionDate"/>
        <result column="store_id" property="store.id"/>
        <result column="store_name" property="store.storeName"/>
    </collection>
</resultMap>
<select id="getStoreWithbooks" resultMap="getBooks">
    SELECT * from store_tbl s LEFT JOIN runoob_tbl r 
    ON s.id = r.store_id WHERE s.id = #{id}
</select>
  • 分步查询封装collection
    先用store_id查询store_name,再用store_id查询Book数据(list集合)
<!--StoreMapper.xml  -->
<!--分步查询,封装collection-->
<resultMap id="getBooksByStep" type="bean.Store">
    <id column="id" property="id"/>
    <result column="store_name" property="storeName"/>
    <collection property="books" select="dao.BookMapper.getBooksByStoreId" 
                                                            column="id"/>
</resultMap>
<select id="getStoreWithBooksByStep" resultMap="getBooksByStep">
    SELECT * FROM store_tbl WHERE id = #{id}
</select>

<!-- BookMapper.xml -->
通过store_id查询Books封装成list
<select id="getBooksByStoreId" resultType="bean.Book">
    SELECT * FROM runoob_tbl WHERE store_id = #{id}
</select>

相关文章

网友评论

      本文标题:Mybatis的映射文件

      本文链接:https://www.haomeiwen.com/subject/wpcznqtx.html