【mybatis】学习总结(二)


动态Sql

mybatis真正强大的地方,是可以灵活的运用sql语句进行查询。

  • if语句

在mapper映射文件中可以使用\标签来对语句接收的参数进行判断,从而动态改变sql语句。

为了避免多次遇到同一段判断代码时的累赘,可以使用SQL片段来重复利用代码。
如下:

<sql id="thereissqlblock">
        <if test="goods!=null and user!=null">
            <if test="user.name!=null and user.name!='' ">
                AND user.password=#{goods.price}
            </if>
        </if>
</sql>

<select id="selectUseIf" parameterType="userQuery" resultType="user">
    SELECT * FROM USER
    <where>
        <include refid="thereissqlblock"></include>
    </where>
</select>

具体分析:
if标签\<>里的test判断的是输入的参数的值,而\<>外则是相应的sql语句块(另外,#表示占位符,$为匹配符)。若不符合if test里的条件,则会执行select * from user,及不设置条件会查询出所有记录,若符合,则会把sql片段拼接到原语句。

  • foreach语句

foreach对应sql语句为:

SELECT * FROM USER WHERE userid=1 OR userid=2 OR userid=3
SELECT * FROM USER WHERE userid IN(1,2,3)

对于多个对象的输入查询,foreach可以解决遍历参数数组的问题。首先在参数对象中定义一个list集合并生成set和get方法,

private    List<T> list;
//set和get方法 

在mapper参数类型parameterType设置为list存放对象类型,接着:

<if test="users!=null">
    <foreach collection="users" item="theuser" open="AND (" close=")" separator="or">
        userid=#{theuser.userid}
    </foreach>
</if>

使用:

User user1=new User();
User user2=new User();
user1.setUserid(1111);
user2.setUserid(1112);
List<User> users=new ArrayList<>();
users.add(user1);
users.add(user2);
userQuery.setUsers(users);
userMapper.selectForeach(userQuery).stream().forEach(System.out::println);

即可查出id为1111,1112的俩条记录。


sql的一对一、一对多

定义表,orders:订单,custom:用户。外键关联
一个用户可发起多个订单,一个订单对应一个用户。
在对应类里添加属性。
orders:private Custom custom;
custom:private List\ orders;

  • 一对一:
订单对用户为一对一关系,则根据订单查用户有如下几种方法:
  1. 创建一个新类继承Orders,在该类里添加custom的属性并生成set和get方法。然后直接使用该类查询即可,实际应用中应该加上一个输入的参数ordersid这里我懒没加

    <mapper namespace="com.me.mapper.OrdersMapper">
        <select id="findCO" resultType="customOrders">
            SELECT custom.*,orders.* FROM custom,orders WHERE orders.customid=custom.id
        </select>
    </mapper>
    
  2. 上面方法是在没有设置private Custom custom属性时候用的,所以其实可以直接把resultType改成orders,但得不到custom对象,不会把写在mapper里的custom.*映射到orders里的custom属性。
  3. 怎么解决2的问题呢?使用resultMap添加association标签关联即可解决

    <resultMap type="orders" id="resultmap1">
        <id column="orderid" property="orderid" />
        <result column="thing" property="thing"/>
        <result column="customid" property="customid"/>
        <association property="custom" javaType="com.me.domain.Custom">
            <id column="customid" property="id"/>
            <result column="name" property="name"/>
            <result column="nowdate" property="nowdate"/>
            <result column="sex" property="sex"/>
        </association>
    </resultMap>
    <select id="findCCO" resultMap="resultmap1">
        SELECT orders.*,custom.* FROM custom,orders WHERE orders.customid=custom.id
    </select>
    

    这里,在resultMap里少添加或者在select后面少写一项属性,得到的对象属性就会少一项属性的值(所以不要偷懒少写属性)。


  • 一对多:

上面的一对一反过来,问题就变成了一对多,即一个custom对应多个orders。
对于一对多关系,我直接介绍最有效率的方法:
使用resultMap:

<resultMap type="custom" id="ccus">
    <id column="id" property="id" />
    <result column="name" property="name" />
    <result column="nowdate" property="nowdate"/>
    <result column="sex" property="sex"/>
    <collection property="orders" ofType="com.me.domain.Orders">
        <id column="order_id" property="orderid"/>
        <result column="thing" property="thing" />
        <result column="customid" property="customid"/>
    </collection>
</resultMap>
<select id="selectCus" resultMap="ccus">
    SELECT c.*,o.orderid order_id,o.thing,o.customid FROM custom c,orders o WHERE c.id=o.customid
</select>

注意这里是collection,执行后会把符合条件的orders一条一条映射到custom的list\属性。

注意事项:如果关联表中有列名和主表列名相同,必须要设置别名,否则查询结果会有问题。

具体可以看这里


  • 多对多:

具体看这篇