常用的高级sql查询

1.根据主键id数组批量修改

 1    void updateByIdArr(Integer[] idArr);
 2    
 3    <update id="updateByIdArr" parameterType="java.util.Arrays" >
 4     <!--
 5       WARNING - @mbggenerated
 6       This element is automatically generated by MyBatis Generator, do not modify.
 7       This element was generated on Tue Nov 01 11:14:38 CST 2016.
 8     -->
 9     update t_usermanage_adviser
10     set status = 0 
11     where id in 
12     <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
13         #{item}
14     </foreach>
15     
16   </update>
View Code

 2.批量插入 更新sql

(1). 弊端
如果传入的更新的值为空,会把相应的值更新为空

 1   int batchInsertOrUpdate(List<TShopAttachment> attachments);
 2   
 3   
 4   <insert id="batchInsertOrUpdate" parameterType="java.util.List">
 5     insert into t_shop_attachment
 6     (
 7       enterprise_id, shop_id, type_id, file_path, uploader, updater, file_name, upload_date,
 8       update_date, status
 9     ) values
10     <foreach collection="list" item="item" index="index" separator=",">
11       (
12       #{item.enterprise_id}, #{item.shop_id}, #{item.type_id}, #{item.file_path}, #{item.uploader},
13       #{item.updater}, #{item.file_name}, #{item.upload_date},
14       #{item.update_date}, #{item.status}
15       )
16     </foreach>
17     ON DUPLICATE KEY UPDATE
18     file_path = VALUES(file_path),
19     updater = VALUES(updater),
20     file_name = VALUES(file_name),
21     update_date = VALUES(update_date)
22   </insert>
View Code

3.关联关系association:1对1关联的三种方法

表结构:

 

order:订单表

order_detail 订单明细表

product 商品表

category 商品分类表

梳理图上的4根关系线:
1、1个用户可以有0个或多个订单:[user表]–>[order表]是1对多(0.n)关系
2、1个有效订单会购买1条或多条商品分录:[order表]–>[order_detail表]是1对多(1.n)关系
3、1条商品分录必定对应一个产品详情:[order_detail表]–>[product表]是1对1关系
4、1个商品分类下可能会有0个或多个商品:[category表]–>[product表]是1对多(0.n)关系
5、所有1对多关系,反过来一定是1对1关系。比如[user表]–>[order表]是1对多(0.n)关系,那么反过来[order表]–>[user表]是1对1关系。每个订单都会有与之对应的唯一用户。
要注意,所有1对1关系,反过来却不一定是1对1关系。比如[order_detail表]–>[product表]是1对1关系,反过来[product表]–>[order_detail表]就不是1对1关系。因为同一个产品可能会在多个不同的订单分录中出现(热门商品大家都愿意买嘛)

[order表]–>[user表]是1对1关系,那么就拿这个来练手。1对1关联关系用于对一个表外键的扩展。
现在要在后台系统中按以下字段显示订单列表。

有三种方式可以实现:

一、扩展新建POJO对象,不使用association标签

step1.我们已经有一个与表对应的Order类,但是没有用户名称,用户地址,联系电话这三个字段。现在新建一个类OrderExtend,扩充字段:

 1 public class OrderExtend extends Order{
 2     public OrderExtend() {
 3         super();
 4     }
 5     /*添加用于展示的用户名称,用户地址,联系电话这三个字段*/
 6     String username;
 7     String address;
 8     String cellphone;
 9 
10     /*下面get和set方法*/
11     getter and setter....
12 }
13 
14 ---------------------
15 作者:唐大麦 
16 来源:CSDN 
17 原文:https://blog.csdn.net/soonfly/article/details/63688288?utm_source=copy 
18 版权声明:本文为博主原创文章,转载请附上博文链接!
View Code

step2.创建接口及Xml

1 public interface OrderExtendMapper {
2     //查询单个订单详情,关联查询用户信息
3     public OrderExtend getByOrderno(String orderno) throws Exception;
4     //查询订单列表,关联查询用户信息
5     public List<OrderExtend> getList() throws Exception;
6 }
View Code
 1 <mapper namespace="twm.mybatisdemo.mapper.OrderExtendMapper">
 2     <select id="getByOrderno" parameterType="String"
 3         resultType="twm.mybatisdemo.pojo.OrderExtend">
 4         SELECT
 5         `order`.*,`user`.username,`user`.address,`user`.cellphone
 6         FROM `order` ,`user`
 7         WHERE `order`.create_userid=`user`.id AND `order`.create_userid=#{id}
 8     </select>
 9 
10     <select id="getList" resultType="twm.mybatisdemo.pojo.OrderExtend">
11         SELECT
12         `order`.*,`user`.username,`user`.address,`user`.cellphone
13         FROM `order`
14         ,`user`
15         WHERE `order`.create_userid=`user`.id
16     </select>
17 </mapper>
View Code

step3.调用

1 public static void main(String[] args) throws Exception {
2         SqlSession session = SqlSessionAssist.getSession();
3 
4         OrderExtendMapper ordermapper = session
5                 .getMapper(OrderExtendMapper.class);
6         OrderExtend order = ordermapper.getByOrderno("M201209012578917");
7         System.out.println(order.getOrderno() + "," + order.getUsername() + ","
8                 + order.getAddress() + "," + order.getCellphone());
9     }
View Code

二、(推荐)用sql联合查询,使用association标签

 1 public class Order{
 2     /*添加用于展示的用户名称,用户地址,联系电话这三个字段*/
 3     String username;
 4     String address;
 5     String cellphone;
 6     User user;
 7 
 8     public User getUser() {
 9         return user;
10     }
11     public void setUser(User user) {
12         this.user = user;
13     }
14     /*下面get和set方法*/
15     getter and setter....
16 }
View Code

step2.创建映射器接口及配置Xml 
twm.mybatisdemo.mapper包下创建 
OrderMapper.java:

1 public interface OrderMapper {
2     //查询单个订单详情,关联查询用户信息
3     public Order getByOrderno(String orderno) throws Exception;
4     //查询订单列表,关联查询用户信息
5     public List<Order> getList() throws Exception;
6 }
View Code

OrderMapper.xml:

 1 <mapper namespace="twm.mybatisdemo.mapper.OrderMapper">
 2     <!-- 定义类型映射 -->
 3     <resultMap type="Order" id="OrderMap">
 4         <!-- 订单表属性 -->
 5         <id column="id" property="id" />
 6         <result column="orderno" property="orderno" />
 7         <result column="create_time" property="create_time" />
 8         <result column="create_userid" property="create_userid" />
 9         <!-- 关联的用户信息 -->
10         <!-- association用于关联查询:
11         property指属性,javaType是要映射的对象的类型。 -->
12         <association property="user" javaType="User">
13             <result column="username" property="username" />
14             <result column="address" property="address" />
15             <result column="cellphone" property="cellphone" />
16         </association>
17     </resultMap>
18 
19     <select id="getByOrderno" parameterType="String"
20         resultMap="OrderMap">
21         SELECT
22         `order`.*,`user`.username,`user`.address,`user`.cellphone
23         FROM `order`
24         ,`user`
25         WHERE `order`.create_userid=`user`.id AND
26         `order`.orderno=#{orderno}
27     </select>
28 
29     <select id="getList" resultMap="OrderMap">
30         SELECT
31         `order`.*,`user`.username,`user`.address,`user`.cellphone
32         FROM `order`
33         ,`user`
34         WHERE `order`.create_userid=`user`.id
35     </select>
36 </mapper>
View Code

step3.调用

 1 public static void main(String[] args) throws Exception {
 2     SqlSession session = SqlSessionAssist.getSession();
 3 
 4     OrderMapper ordermapper = session.getMapper(OrderMapper.class);
 5     Order order = ordermapper.getByOrderno("M201209012578917");
 6     System.out.println(order.getOrderno() + ","
 7             + order.getUser().getUsername() + ","
 8             + order.getUser().getAddress() + ","
 9             + order.getUser().getCellphone());
10 
11 }
View Code

什么是延迟加载?如果先查询订单信息即可满足业务要求就不会去查询用户,只有当用到用户信息时再查询用户信息。
对用户信息按需去查询就是延迟加载。
比如上面,只有当调用Order中的getUser方法获取关联的user数据时,才会触发数据库查询user表。

mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。
lazyLoadingEnabled:全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。允许值有:true | false。默认值:false
aggressiveLazyLoading:当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。允许值有:true | false。默认值:true

和第二种方式比,其它都不变。只是DAOImplement层有一些变化,XML文件要调整三处:

第一处:新增一个用户查询语句:

1 <!-- 新增一个用户查询语句:getUser -->
2 <select id="getUser" parameterType="int" resultType="User">
3     SELECT
4     `username`,`address`,`cellphone`
5     FROM `user`
6     WHERE `id` =#{_parameter}
7 </select>
View Code

第二处:把原来resultMap的association标签改为

1 <association property="user" javaType="User" column="create_userid" select="getUser" />
View Code

第三处:把getByOrderno和getList查询语句改为普通的select单表查询。

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 3 <mapper namespace="twm.mybatisdemo.mapper.OrderMapper">
 4     <!-- 定义类型映射 -->
 5     <resultMap type="Order" id="OrderMap">
 6         <!-- 订单表属性 -->
 7         <id column="id" property="id" />
 8         <result column="orderno" property="orderno" />
 9         <result column="create_time" property="create_time" />
10         <result column="create_userid" property="create_userid" />
11         <!-- 关联的用户信息 -->
12         <!-- association用于关联查询: property指属性,javaType是要映射的对象的类型。 -->
13         <association property="user" javaType="User" column="create_userid"
14             select="getUser" />
15     </resultMap>
16 
17 <!-- 新增一个用户查询:getUser。getUser这一段可以删掉,用user对象的查询方法 -->
18 <select id="getUser" parameterType="int" resultType="User">
19     SELECT
20     `username`,`address`,`cellphone`
21     FROM `user`
22     WHERE `id` =#{_parameter}
23 </select>
24 
25     <select id="getByOrderno" parameterType="String" resultMap="OrderMap">
26         SELECT * FROM `order`  WHERE `order`.orderno=#{orderno}
27     </select>
28 
29     <select id="getList" resultMap="OrderMap">
30         SELECT * FROM `order` 
31     </select>
32 </mapper>
View Code

一切OK了。 
association的几个属性: 
property:指定内部对象属性名 
javaType:内部映射的对象的类型。 
column:要传给select语句的参数,相当于指定外键字段。 
select:指定用户查询语句的ID

事实上,大多数业务场景显示的表格,都会用到多个表字段。
如果采用延迟加载,会存在N+1问题。
什么是N+1问题呢?
每一个获取Order内部的User对象,都会进行一次select查询
那么当运行过程中执行Order的getList方法时,SQL首先进行1次查询,查询结果如果有N条订单记录,那么实际在每条订单中显示过程中还要运行一次select用户的查询,共n次。
SQL总共执行了n+1次。相比第二种方法的只进行一次联合查询,这种方式无疑是低效的。
如果业务场景的表格显示字段,并没有跨表,那么可以采用延迟加载方式 

猜你喜欢

转载自www.cnblogs.com/xiaoxiaoccaiya/p/9768314.html
今日推荐