当前位置: 首页 > news >正文

【Mybatis】动态sql

讲之前,先把实体类给写出来

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

1.if标签

我们根据实体类的不同取值,使用不同的sql语句来查询,例如可以根据id来查询,根据name来查询,也可以同时根据id和name来查询。

下面就来演示如何查询

首先创建接口

//复杂条件查询
public List<User> findByUser(User user);

然后对映射文件进行配置

<select id="findByUser" resultType="user" parameterType="user">   
select * from user where 1=1    
<if test="username!=null and username != ''">        
and username=#{username}    
</if>    
<if test="birthday!=null">        
and birthday=#{birthday}    
</if>    
<if test="sex!=null">        
and sex=#{sex}   
</if>    
<if test="address!=null">        
and address=#{address}    
</if>
 </select>

这里就用上了if标签,这个if就相当于java中的if判断,只要if标签中的条件成立,就会将改字段拼接到前面的select* from user where 1=1的后面。很容易理解,就是只要符合if标签中的条件就可以把if标签内的语句拼接到前面的语句的后面。

但是你有没有注意这里的where后面加了个1=1是不是有点奇怪,但其实他是为了使拼接的sql语句语法正确,不然第一个正确的if标签内的语句拼接上去后where and就会出现语法错误,所以加了个1=1,反正它又不会影响其他的判断。

测试方法

public class TestUser {    
UserDao userDao;    
SqlSession sqlSession;    
//抽取重复的代码    
@Before //这个@Before注解修饰的方法会在@Test修饰的方法之前执行    
public void before() throws Exception{        
//加载配置文件        
InputStream in = 
Resources.getResourceAsStream("SqlMapConfig.xml");        
//创建SqlSessionFactoryBuilder        
SqlSessionFactoryBuilder builder = new 
SqlSessionFactoryBuilder();        
//创建SqlSessionFactory对象     
SqlSessionFactory sessionFactory = builder.build(in);     
   
        //创建SqlSession对象        
        sqlSession = sessionFactory.openSession(true);        
        //生成代理对象        
        userDao = sqlSession.getMapper(UserDao.class);   
    }    
    
    @After //@After注解修饰的方法在@Test注解修饰的方法之后执行    
    public void after(){        
        sqlSession.close();    
    }   
    
    @Test   
    public void testFindByUser(){        
        User user = new User();       
        user.setSex("男");       
        user.setAddress("上海");        
        List<User> userList = userDao.findByUser(user);        
        for(User u : userList){            
            System.out.println(u);       
        }    
    }
 }

这里的@Before注解就是使被它标记的方法在@test标记的方法之前的方法执行。

@After注解就是使被它标记的方法在@test标记的方法之后的方法执行。

这么做的原因就是当有多个sql语句要执行时,不用每一次都创建相关的对象,然后再关闭。就相当于把这一段代码给提取了出来。

2.where标签

为了简化上面的where 1=1,我们可以用where标签来简化。

 <select id="findByUser" resultType="user" parameterType="user">   
 
    select * from user    
    <where>        
        <if test="username!=null and username != ''">            
            and username=#{username}        
        </if>        
        <if test="birthday!=null">            
            and birthday=#{birthday}        
        </if>       
        <if test="sex!=null">            
            and sex=#{sex}        
        </if>        
        <if test="address!=null">            
        and address=#{address}        
        </if>    
        </where>   
</select>

这里进行sql拼接的时候会自动把第一个满足条件的if标签中的语句的and给自动去掉。

3.set标签

set标签可以用来实现动态修改

接口

// 动态修改
public void updateUser(User user);

映射文件配置

<update id="updateByUser" parameterType="user">    
update user    
<set>        
<if test="username!=null and username != '' ">           
username=#{username},        
</if>        
<if test="birthday!=null">           
birthday=#{birthday},        
</if>       
<if test="sex!=null and sex != '' ">            
sex=#{sex},       
</if>        
<if test="address!=null and address != '' ">            
address=#{address},        
</if>    
</set>    
where id=#{id}
 </update>

 还是一样的,就是满足if标签中满足条件的语句拼接上去,别忘了后面还有一个后缀,就是where id=#{id}.

测试

@Test
 public void testUpdateByUser(){    
    User user = new User();   
    user.setId(60);    
    user.setBirthday(new Date());    
    user.setAddress("加拿大");    
    userDao.updateByUser(user);
 }

4.添加

定义接口

 public void addUser(User user);

映射文件配置

 <sql id="key">    
    <trim suffixOverrides=",">        
        <if test="username!=null and username != '' ">           
            username,        
        </if>  
      
        <if test="birthday!=null and username != '' ">           
            birthday,        
        </if>   
     
        <if test="sex!=null and username != '' ">           
            sex,        
        </if>   
     
        <if test="address!=null and username != '' ">            
            address,        
        </if> 
   
    </trim>
 </sql>


<sql id="value">    
   <trim suffixOverrides=",">        
    
    <if test="username!=null and username != '' ">           
            #{username},        
    </if>   
     
    <if test="birthday!=null and username != '' ">           
    #{birthday},        
    </if>   
     
    <if test="sex!=null and username != '' ">            
    #{sex},        
    </if>     
   
    <if test="address!=null and username != '' ">            
    #{address},        
    </if>    

   </trim>
</sql>


 <insert id="addUser" parameterType="user">    
insert into user(<include refid="key"/>)  values(<include refid="value"/>)
 </insert>

 这里就相当于把两个sql中满足条件的语句插入insert标签中,这里又几点要说明。

首先sql中的id的取值随便去什么,只要保证它的唯一性就行了,与后面insert标签中的refid相对应就行了

然后这里的trim标签是用来对sql语句进行灵活拼接的,suffixOverrides=","就是用来删除拼接后的sql语句末尾的逗号的。

测试

@Test
 public void testAddUser(){   
User user = new User();    
user.setUsername("张卫健");    
user.setAddress("香港");    
userDao.addUser(user);
 }

5.choose when otherwise标签

定义接口

//根据复杂条件查询
public List<User> findByCondition(User user);

映射文件配置

<select id="findByCondition" parameterType="user" 
resultType="user">     
select * from user     
 <where>        
  <choose>             
   <when test="username!=null and username != ''">       
   username=#{username}   
   </when>   
          
   <when test="birthday!=null and birthday != ''">       
             birthday=#{birthday}             
   </when>
             
   <when test="sex!=null and sex != ''">                 
                sex=#{sex}             
   </when>             
           
   <when test="address!=null and address != ''">         
        
             address=#{address}             
   </when>   
          
   <otherwise>                 
                id = #{id}             
   </otherwise>
         
  </choose>     
 </where>
</select>

 这里的when otherwise就相当于if else语句,与前面的if标签不同,它这里只要满足一个条件就会中断,不像if中所有条件都要判断。

这里的otherwise就相当于else

测试

 @Test
 public void test12() throws Exception{    
    User user = new User();    
    user.setUsername("ONeal");    
    user.setSex("男");    
    user.setAddress("美国");    
    List<User> userList = userDao.findByCondition(user);    
    userList.forEach(u ->{        
        System.out.println(u);    
    });
 }

6.foreach标签

当我们要根据id同时查询多个记录时,就是要输多个id来查询多个记录时,就需要用到foreach来进行操作。

有两种方式进行操作

第一种:将批量id封装到数组中

定义接口

//批量删除 将批量id封装到数组里面
public void deleteUserByIds(@Param("ids")Integer[] ids);

@Param("ids")为 Integer[] ids 这个参数指定了别名 ids。这样在对应的 SQL 映射文件里,就可以使用 ids 来引用这个参数数组 

映射文件配置

<delete id="deleteUserByIds">    
delete from user where id in     
(      
<foreach collection="ids" item="id" separator=",">          
#{id}      
</foreach>    
)
 </delete>

 这里要注意的一点是,这里的sql语句是删除操作,所以用的标签是delete,如果你是要执行查询的操作,那么就是使用select标签

这里的collection就是用来接收封装id的集合的

item用来指定每次从集合中迭代取出的元素的别名,其实就只要保证item的值和#{}中的值一样就够了

separator是用来对迭代取出来的数字进行分格的,这里的separator=","意思就是用逗号将迭代取出来的数字进行分格

测试

@Test
 public void test12() throws Exception{    
Integer[] ids = {1,2,3,4,5};    
userDao.deleteUserByIds(ids);
 }

可以来看一下运行台中sql的形式的样子

 

我们也可以不用加@Param注解,可以 

​
<delete id="deleteUserByIds">    
delete from user where id in     
(      
<foreach collection="array" item="id" separator=",">          
#{id}      
</foreach>    
)
 </delete>

​

直接指定为数组类型也是可以的,也就是说这里固定要填array。

第二种:将批量id封装到list集合中

定义接口

//批量删除 将批量id封装到List集合里面
public void deleteUserByIds(List<Integer> ids);

映射文件配置

<delete id="deleteUserByIds" parameterType="int">    
delete from user where id in    
(      
<foreach collection="list" item="id" separator=",">          
#{id}      
</foreach>    
)
 </delete>

 这里的collection只能写list,其他的和前面一样的理解。

测试

@Test
 public void test12() throws Exception{    
List<Integer> ids = new ArrayList<>();    
ids.add(1);    
ids.add(2);    
ids.add(3);    
ids.add(4);    
ids.add(5);    
userDao.deleteUserByIds(ids);
 }

看一下控制台中被拼接的sql语句

 

总结: 当我们传递一个 List 实例或者数组作为参数对象传给 MyBatis。当你这么做的时 候,MyBatis 会自动将它包装在一个 Map 中,用名称在作为键。List 实例将会以“list” 作为键,而数组实例将会以“array”作为键。所以,当我们传递的是一个List集合时, mybatis会自动把我们的list集合包装成以list为Key值的map 

7.批处理

从名字就可以看出来就是批量处理一堆数据的

它有两种方式进行实现。下面以一个需求来演示

需求:批量增加数据

第一种:将批量新增的数据 放在List集合里面,遍历集合循环新增数据即可。

@Test
 public void test13() throws Exception{    
UserDao userDao = sqlSession.getMapper(UserDao.class);    
List<User> userList = new ArrayList<User>();    
User user1 = new User();    
user1.setUsername("测试数据3");    
user1.setBirthday(new Date());    
user1.setSex("男");    
user1.setAddress("测试数据3");    
User user2 = new User();    
user2.setUsername("测试数据4");    
user2.setBirthday(new Date());    
user2.setSex("男");    
user2.setAddress("测试数据4");    
userList.add(user1);    
userList.add(user2);    
//批量新增    
 for(User user : userList){        
userDao.addUser(user);    
}    
sqlSession.commit();
}

看一下控制台执行结果

这里sql语句执行了多次,与数据库进行多次访问,效率太慢了。

第二种:开启批处理指令,使用批处理的方式进行数据的新增 

有两种方式开启批量处理

第一种:在mybatis的核心配置文件上开启 。

<settings>    
<setting name="defaultExecutorType" value="BATCH"/>
 </settings>

    第二种方式是:在创建SqlSession对象的时候,指定开启批处理 

sqlSession = sessionFactory.openSession(ExecutorType.BATCH,false);

查看控制台效果

这里语句只执行了一次,效率变高了。

相关文章:

  • HarmonyOS NEXT 组件状态管理的对比
  • IoT设备测试:从协议到硬件的全栈验证体系与实践指南
  • 某公司制造业研发供应链生产数字化蓝图规划P140(140页PPT)(文末有下载方式)
  • 论文笔记(七十三)Gemini Robotics: Bringing AI into the Physical World
  • fastapi 使用 TORTOISE-ORM
  • stm32HAL库驱动gt911触摸屏
  • 麦肯锡咨询某著名企业数字化转型创新驱动与智慧企业构建(40页PPT)(文末有下载方式)
  • 计算机体系结构作业2
  • dfs(二十四)47. 全排列 II
  • 【项目合集】基于ESP32的智能盲人饮水机
  • Pygame实现记忆拼图游戏14
  • 价值流图分析VSM(75页PPT)(文末有下载方式)
  • 前端项目中应该如何选择正确的图片格式
  • 高并发编程有哪些规范?
  • LeetCode hot 100 每日一题(12)——238.除自身以外数组的乘积
  • 单调队列【C/C++】
  • 在 Linux 系统上部署 Deepseek AI 的全面指南‌
  • (* IOB = “FORCE“ *) 的使用分享
  • 鸿蒙NEXT项目实战-百得知识库04
  • 【机器学习】什么是逻辑回归
  • 音乐节困于流量
  • 中拉互联网发展与合作论坛在西安开幕
  • “大型翻车现场”科技满满,黄骅打造现代化港口和沿海新城典范
  • 上海能源科技发展有限公司原董事长李海瑜一审获刑13年
  • 科创板年内第3家!健信超导IPO获受理,拟募资8.65亿
  • 打击网络谣言、共建清朗家园,中国互联网联合辟谣平台2025年4月辟谣榜