mybatis02-核心配置文件、返回主键值、SQL片段、事务处理、动态SQL

news2024/12/26 22:49:21

Mybatis02

一、mybatis核心配置文件

  • 在主配置config.xml中,定义了很多标签,现在只是使用了一部分标签,主配置文件中可以出现的标签 用dtd文 件进行约束。

1、标签的配置规范,查看dtd规范文件

<?xml version="1.0" encoding="UTF-8" ?>
<!--

Copyright 2009-2016 the original author or authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->
<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>

<!ELEMENT databaseIdProvider (property*)>
<!ATTLIST databaseIdProvider
type CDATA #REQUIRED
>

<!ELEMENT properties (property*)>
<!ATTLIST properties
resource CDATA #IMPLIED
url CDATA #IMPLIED
>

<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
value CDATA #REQUIRED
>

<!ELEMENT settings (setting+)>

<!ELEMENT setting EMPTY>
<!ATTLIST setting
name CDATA #REQUIRED
value CDATA #REQUIRED
>

<!ELEMENT typeAliases (typeAlias*,package*)>

<!ELEMENT typeAlias EMPTY>
<!ATTLIST typeAlias
type CDATA #REQUIRED
alias CDATA #IMPLIED
>

<!ELEMENT typeHandlers (typeHandler*,package*)>

<!ELEMENT typeHandler EMPTY>
<!ATTLIST typeHandler
javaType CDATA #IMPLIED
jdbcType CDATA #IMPLIED
handler CDATA #REQUIRED
>

<!ELEMENT objectFactory (property*)>
<!ATTLIST objectFactory
type CDATA #REQUIRED
>

<!ELEMENT objectWrapperFactory EMPTY>
<!ATTLIST objectWrapperFactory
type CDATA #REQUIRED
>

<!ELEMENT reflectorFactory EMPTY>
<!ATTLIST reflectorFactory
type CDATA #REQUIRED
>

<!ELEMENT plugins (plugin+)>

<!ELEMENT plugin (property*)>
<!ATTLIST plugin
interceptor CDATA #REQUIRED
>

<!ELEMENT environments (environment+)>
<!ATTLIST environments
default CDATA #REQUIRED
>

<!ELEMENT environment (transactionManager,dataSource)>
<!ATTLIST environment
id CDATA #REQUIRED
>

<!ELEMENT transactionManager (property*)>
<!ATTLIST transactionManager
type CDATA #REQUIRED
>

<!ELEMENT dataSource (property*)>
<!ATTLIST dataSource
type CDATA #REQUIRED
>

<!ELEMENT mappers (mapper*,package*)>

<!ELEMENT mapper EMPTY>
<!ATTLIST mapper
resource CDATA #IMPLIED
url CDATA #IMPLIED
class CDATA #IMPLIED
>

<!ELEMENT package EMPTY>
<!ATTLIST package
name CDATA #REQUIRED
>

2、properties标签详解

​ 在使用 properties 标签配置时,在xml文件中可以引用 properties 属性文件中key的值,后面修改properties 属性文件中key的值时,不用修改mybatis.xml文件,从而提高了效率。

(1)jdbc.propertiessh属性文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/sms
root=root
password=root
(2)在mybatis.xml文件中引用属性文件中key的值
<!--配置连接数据库的信息:动态的读-->
<properties resource="jdbc.properties"></properties>
<!--配置mybatis的环境-->
<environments default="development">
    <!--配置环境-->
    <environment id="development">
        <!--配置事务的类型-->
        <transactionManager type="JDBC"></transactionManager>
        <!--配置链接数据库的信息:使用的是 数据源[连接池]-->
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${root}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>
(3) 测试

项目结构

在这里插入图片描述

引入依赖pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>day0417</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <spring.version>5.2.5.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

实体类:Student

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student {

    private int id;
    private String name;
    private String gender;
    private Date birthday;
    private String s_class;
    private String photo;
}

接口StudentDao定义方法

import com.etime.pojo.Student;

import java.util.List;

public interface StudentDao {
    List<Student> getAllStudents();
}

编写StudentMapper.xml文件代码

<?xml version="1.0" encoding="UTF-8" ?>
<!--
引入dtd约束-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 是当前mapper对应的接口-->
<mapper namespace="com.etime.dao.StudentDao">
    <select id="getAllStudents" resultType="com.etime.pojo.Student">
        select * from student;
    </select>
</mapper>

配置mybatisConfig.xml文件信息

<?xml version="1.0" encoding="UTF-8"?>
<!--引入dtd约束-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--配置连接数据库的信息:动态的读-->
    <properties resource="jdbc.properties"></properties>
    <!--配置mybatis的环境-->
    <environments default="development">
        <!--配置环境-->
        <environment id="development">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置链接数据库的信息:使用的是 数据源[连接池]-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${root}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--注册StudentDao接口映射文件位置-->
    <mappers>
        <mapper resource="mapper/StudentMapper.xml"></mapper>
    </mappers>
</configuration>

编写@Test方法

package com.etime.test;

import com.etime.dao.StudentDao;
import com.etime.pojo.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class StudentTest {

    @Test
    public void test01() throws IOException {
        InputStream in = Resources.getResourceAsStream("mybatisConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession sqlSession = factory.openSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        List<Student> allStudents = studentDao.getAllStudents();
        System.out.println(allStudents);
        sqlSession.close();
    }
}

3、typeAliases标签详解

  • 前面 接口的 StudentDao 配置文件中使用的是默认别名(完全限定名),我们也可以采用自定义别名方式开发

(1)方式1

在mybatisConfig.xml中定义别名
  • 注意dtd约束中typeAliases的顺序
<configuration>
    <!--配置连接数据库的信息:动态的读-->
    <properties resource="jdbc.properties"></properties>
    <!--给实体类取别名-->
    <!--方法1-->
    <typeAliases>
        <!--type:实体类的完全限定名,实体类在项目中的位置-->
        <!--alias:给实体类取得别名-->
        <typeAlias type="com.etime.pojo.Student" alias="stu"></typeAlias>
    </typeAliases>
</configuration>
在StudentMapper.xml中使用别名
引入dtd约束-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 是当前mapper对应的接口-->
<mapper namespace="com.etime.dao.StudentDao">
    <select id="getAllStudents" resultType="stu">
        select * from student;
    </select>
</mapper>
测试和properties标签详解的@Test方法一致

(2)方式2

  • 不写alias(不指定别名)的时候默认别名为 类名
在mybatisConfig.xml中定义别名
<!--方法2-->
<typeAliases>
    <!--type:实体类的完全限定名,实体类在项目中的位置-->
    <typeAlias type="com.etime.pojo.Student"></typeAlias>
</typeAliases>
在StudentMapper.xml中使用别名
<select id="getAllStudents" resultType="Student">
    select * from student;
</select>
测试和properties标签详解的@Test方法一致

(3)方式3

  • 为某个包下的所有类批量起别名,在name属性中同样写包的全路径,在包下的类默认别名为类名
在mybatisConfig.xml中定义别名
<typeAliases>
    <package name="com.etime.pojo"/>
</typeAliases>
在StudentMapper.xml中使用别名
<select id="getAllStudents" resultType="Student">
    select * from student;
</select>
测试和properties标签详解的@Test方法一致

4、mappers映射器标签详解

  • mappers映射器用于指定映射文件的位置

(1)方式1

  • resource属性
<!--注册StudentDao接口映射文件位置-->
<mappers>
    <mapper resource="mapper/StudentMapper.xml"></mapper>
</mappers>
  • 测试方法:在入门的时候使用的是 resource属性

(2)方式2

  • class属性

  • 要求映射的xml文件必须放到接口文件所在的包,且映射文件名必须和接口文件名保持一致

  • 注意:resource 资源包新建的是文件夹,不是包

    • resource 资源包新建包方式:com/etime/dao
    • resource 资源包重命名方式:先将文件夹改为包的一级名:例:com,建第二级包:etime/,建第三级包:dao/
项目结构

在这里插入图片描述

注册映射文件的位置
<!--注册StudentDao接口映射文件位置-->
<mappers>
    <!--<mapper resource="mapper/StudentMapper.xml"></mapper>-->
    <mapper class="com.etime.dao.StudentDao"></mapper>
</mappers>
  • 测试方法:和方式1的@Test方法一致

(3)方式3

  • package标签的name属性
  • 为所有 dao层下的 接口.java的映射文件注册位置
  • 要求映射的xml文件必须放到接口文件所在的包,且映射文件名必须和接口文件名保持一致
<mappers>
    <!--<mapper resource="mapper/StudentMapper.xml"></mapper>-->
   <!-- <mapper class="com.etime.dao.StudentDao"></mapper>-->
    <package name="com.etime.dao"/>
</mappers>
  • 测试方法:和方式1的@Test方法一致

二、mybatis返回主键值

  • 对于 自增主键 在某些业务中保存一个对象后,需要使用到这个主键完成后续的业务逻辑,就需要获取该主键值
  • 主要针对新增操作

1、在接口StudentDao中定义 新增方法

// 添加学生信息
int addStudent(Student student);

2、在StudentDao.xml映射文件中 配置新增信息

(1)方法1

  • useGeneratedKeys::表示开启获取自增主键值。

    • true:开启
    • false:关闭
  • keyProperty:表示从表中取到主键值后赋给Student类中的哪个属性。

<insert id="addStudent" parameterType="Student"  useGeneratedKeys="true" keyProperty="id">
    insert into student(id,name,gender,birthday,s_class,photo) values(#{id},#{name},#{gender},#{birthday},#{s_class},#{photo});
</insert>

(2)方法2

  • keyColumn:指定取数据库中哪一列的值(通常指主键列)
  • keyProperty: 表示取出主键值后赋值Student对象的哪个属性(实体类)
  • resultType: 表示返回对象的属性类型
  • order:表示完后sql语句之前还是之后把主键值赋给实体类对应属性。
    • after
    • before
<insert id="addStudent" parameterType="Student">
     <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
         select last_insert_id()
     </selectKey>
    insert into student(name,gender,birthday,s_class,photo) values(#{name},#{gender},#{birthday},#{s_class},#{photo});
</insert>

(3)测试

@Test
public void test02() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    SqlSession sqlSession = factory.openSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student(0, "li李", "男", null, "1011", null);
    System.out.println("student 前 " + student);
    int res = studentDao.addStudent(student);
    System.out.println("add res = " + res);
    System.out.println("student 后 " + student);
    sqlSession.commit();
    sqlSession.close();
}

三、SQL片段

1、使用场景

​ 我们在开发过程中,SQL的拼接很常见,有很多对拼接的sql具有重复性高的特点,有sql冗余,不仅不美观还导致映射文件配置臃肿。

2、解决办法

​ 把重复的sql抽取出来,作为公用的sql片段,尤其在动态sql中应用中更加显著,提高可重用性。

3、编写SQL片段示例代码

1、在StudentDao.xml文件中定义SQL片段

<sql id="sql1">
    name,gender,birthday
</sql>

2、在StudentDao.xml文件中使用SQL片段

<select id="getAllStudents" resultType="Student">
    select <include refid="sql1"></include> from student;
</select>
  • refid 的值是sql标签对应的id。 id要唯一。

3、测试

@Test
public void test01() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    SqlSession sqlSession = factory.openSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    List<Student> allStudents = studentDao.getAllStudents();
    /*System.out.println(allStudents);*/
    // 打印输出集合中的每一个对象
    allStudents.forEach(System.out::println);
    sqlSession.close();
}
  • allStudents.forEach(System.out::println); :该写法要及jdk1.8或之后的才行

四、mybatis 事务处理

1、JDBC事务提交

​ 在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。

2、mybatis 框架事务提交

​ mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC的setAutoCommit()方法来设置事务提交方式的。

3、@Test分析

​ 我们的 Connection 的整个变化过程,通过分析我们能够发现之前的 CUD 操作过程中,我们都要手动进行事务的提交,原因是 setAutoCommit()方法,在执行时它的值被设置为 false 了,所以我们在CUD操作中,必须通过 sqlSession.commit()方法来执行提交操作。

4、总结

​ 为什么 CUD 过程中必须使用 sqlSession.commit()提交事务?主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提交。

5、通过工具类实现自提交,实现增删改

(1)修改工具类中的代码

package com.etime.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionUtil {

    private static SqlSession sqlSession;

    static {
        InputStream in = null;
        try {
            // 加载配置文件
             in = Resources.getResourceAsStream("mybatisConfig.xml");
            // 用于读取配置文件内容,生成SqlSessionFactory
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
            // 获取SqlSession
            sqlSession = sqlSessionFactory.openSession(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

   public static SqlSession getSqlSession(){
        return sqlSession;
   }
}

(2)测试:将手动提交删除 和 获得SqlSession对象的过程替换成使用工具类获得、

@Test
public void test02() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student(0, "li李", "男", null, "1011", null);
    System.out.println("student 前 " + student);
    int res = studentDao.addStudent(student);
    System.out.println("add res = " + res);
    System.out.println("student 后 " + student);
    sqlSession.close();
}

五、mybatis 动态SQL

  • 概述:
    • SQL 时动态拼接成的,根据传入的变量值进行逻辑操作,并动态拼接,方便实现多条件下的数据库操作。
    • 在业务逻辑复杂,即简单 SQL 无法完成时,需要拼接时就要使用动态SQL。

1、where 标签

  • where标签用于代替sql中的where关键字,可以根据条件判断是否附加where关键字。
  • 如果where标签中有条件成立就会附加where关键字,如果没有成立的条件就不会附加where关键字。
  • 可以去掉离他最近一个无关的and 或or关键字。
  • where标签的书写格式为添写附加条件。

(1)在接口中定义方法

List<Student> getStudentByNameAndGender(Map<String,Object> map);

(2)在映射文件中配置sql语句

<select id="getStudentByNameAndGender" parameterType="Map" resultType="Student">
    select * from student
    <where>
        name=#{name} and gender=#{gender}
    </where>
</select>

(3)测试

@Test
public void test03() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Map<String,Object> map = new HashMap<>();
    map.put("name","李");
    map.put("gender","男");
    List<Student> students = studentDao.getStudentByNameAndGender(map);
    students.forEach(System.out::println);
    sqlSession.close();
}

2、if 标签

  • if标签表示逻辑条件判断
  • 如果条件成立就附加之间的sql语句,如果条件不成立就不附加之间的sql语句。
  • 书写格式为:sql语句

(1)在接口中定义方法

List<Student> getStudentByNameAndGender(Student student);

(2)在映射文件中配置sql语句

<select id="getStudentByNameAndGender" parameterType="Student" resultType="Student">
    select * from student
    <where>
        <if test="name != null">
            and name=#{name}
        </if>
        <if test="gender != null">
            and gender=#{gender}
        </if>
    </where>
</select>

(3)测试

@Test
public void test04() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student(0, null, "男", null, null, null);
    List<Student> students = studentDao.getStudentByNameAndGender(student);
    students.forEach(System.out::println);
    sqlSession.close();
}

总结

  • 通过产生的sql语句可以看出,当if标签中test属性表达式为true时,就会附加if标签之间的条件。

注意

  • 标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法

3、set 标签

  • set标签用于更新语句中
  • 代替set关键字,可以有效对指定字段进行更新,提升sql的执行效率
  • 当set标签中有条件成立时就会附加set标签,set标签会去除无关的逗号。

(1)在接口中定义方法

int updateStudent(Student student);

(2)在映射文件中配置sql语句

<update id="updateStudent" parameterType="Student">
    update student
    <set>
        <if test="name != null">
            name=#{name},
        </if>
        <if test="gender != null">
            gender=#{gender},
        </if>
        <if test="birthday != null">
            birthday=#{birthday},
        </if>
        <if test="s_class != null">
            s_class=#{s_class},
        </if>
        <if test="photo != null">
            photo=#{photo},
        </if>
    </set>
    where id=#{id}
</update>

(3)测试

@Test
public void test05() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student(198, "li李", "男", null, "1011", null);
    int res = studentDao.updateStudent(student);
    System.out.println("update res = " + res);
    sqlSession.close();
}

4、trim 标签

  • trim标签为万能标签,可用于替换set或where等。
  • prefix表示要附加的前缀关键字
  • suffix表示要附加的后缀关键字
  • prefixOverrides表示要忽略前置字符
  • suffixOverrides表示要忽略后置字符

(1)在接口中定义方法

List<Student> getStudentByNameAndGender(Student student);
int updateStudent(Student student);

(2)在映射文件中配置sql语句

应用于where
<select id="getStudentByNameAndGender" parameterType="Student" resultType="Student">
    select * from student
    <trim prefix="where" prefixOverrides="and">
        <if test="name != null">
            and name=#{name}
        </if>
        <if test="gender != null">
            and gender=#{gender}
        </if>
    </trim>
</select>
应用于set
<update id="updateStudent" parameterType="Student">
    update student
    <trim prefix="set" suffixOverrides=",">
        <if test="name != null">
            name=#{name},
        </if>
        <if test="gender != null">
            gender=#{gender},
        </if>
        <if test="birthday != null">
            birthday=#{birthday},
        </if>
        <if test="s_class != null">
            s_class=#{s_class},
        </if>
        <if test="photo != null">
            photo=#{photo},
        </if>
    </trim>
    where id=#{id}
</update>

(3)测试

@Test
public void test04() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student(0, null, "男", null, null, null);
    List<Student> students = studentDao.getStudentByNameAndGender(student);
    students.forEach(System.out::println);
    sqlSession.close();
}

@Test
public void test05() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student(198, "li李", "女", null, "1011", null);
    int res = studentDao.updateStudent(student);
    System.out.println("update res = " + res);
    sqlSession.close();
}

5、choose 标签

  • choose标签作用条件判断来拼接指定的条件
  • 它和if不太相同,choose似类于java中的switch语句用法,要有条件成立,其它判断将得不到执行,如果所有条件都不成立则执行otherwise标签中的内容。

(1)在接口中定义方法

List<Student> getStudentByNameAndGender(Student student);

(2)在映射文件中配置sql语句

<select id="getStudentByNameAndGender" parameterType="Student" resultType="Student">
    select * from student
    <where>
        <choose>
            <when test="name != null">
                and name=#{name}
            </when>
            <when test="gender != null">
                and gender=#{gender}
            </when>
            <otherwise>
                and s_class=#{s_class}
            </otherwise>
        </choose>
    </where>
</select>

(3)测试

@Test
public void test06() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student(0, null, "男", null, "1101", null);
    List<Student> students = studentDao.getStudentByNameAndGender(student);
    students.forEach(System.out::println);
    sqlSession.close();
}

6、foreach 标签

  • foreach标签表示循环,对sql中有重复的部分可以使用此循环来动态拼接sql语句。

  • 可以实现批量添加、批量删除、批量更新操作。

  • foreach标签中有很多的属性,请参考下面的Foreach标签属性表。

    • 属性名称含义
      collection指定你要使用的集合类型(集合名称全为小写)例:list
      item集合中每个元素。
      open在起始时,需要附加字符串,只附加一次。
      close在结束时,需要附加字符,只附加一次。
      separator在每个循环结时需要附加的字符串。
      index每个循环的索引值。

(1)在接口中定义方法

int addSomeStudent(List<Student> list);
int updateSomeStudent(List<Student> list);
int deleteSomeStudent(List<Integer> ids);

(2)在映射文件中配置sql语句

  • **注意:**批量修改时,数据库url后面需要添加allowMultiQueries=true,否则你会失败的很惨哦

    • driver=com.mysql.jdbc.Driver
      url=jdbc:mysql://localhost:3306/sms?allowMultiQueries=true
      root=root
      password=root
      
<insert id="addSomeStudent" parameterType="List">
    insert into student(name,gender,birthday,s_class,photo) values
    <foreach collection="list" item="stu" separator=",">
        (#{stu.name},#{stu.gender},#{stu.birthday},#{stu.s_class},#{stu.photo})
    </foreach>
</insert>
<update id="updateSomeStudent" parameterType="List">
    <foreach collection="list" item="stu" separator=";">
        update student set name=#{stu.name},gender=#{stu.gender},birthday=#{stu.birthday},s_class=#{stu.s_class},photo=#{stu.photo} where id=#{stu.id}
    </foreach>
</update>
<delete id="deleteSomeStudent" parameterType="List">
    delete from student where id in
    <foreach collection="list" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</delete>

(3)测试

@Test
public void test07() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student s1 = new Student(0, "李一", "男", null, "1101", "li1.jpg");
    Student s2 = new Student(0, "李二", "男", null, "1101", "li2.jpg");
    Student s3 = new Student(0, "李三", "男", null, "1101", "li3.jpg");
    List<Student> list = new ArrayList<>();
    list.add(s1);
    list.add(s2);
    list.add(s3);
    int res = studentDao.addSomeStudent(list);
    System.out.println("add some res = " + res);
    sqlSession.close();
}

@Test
public void test08() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    Student s1 = new Student(199, "李一111", "男", null, "1111", "li1.jpg");
    Student s2 = new Student(200, "李二222", "男", null, "1111", "li2.jpg");
    Student s3 = new Student(201, "李三333", "男", null, "1111", "li3.jpg");
    List<Student> list = new ArrayList<>();
    list.add(s1);
    list.add(s2);
    list.add(s3);
    int res = studentDao.updateSomeStudent(list);
    System.out.println("update some res = " + res);
    sqlSession.close();
}

@Test
public void test09() throws IOException {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    List<Integer> list = new ArrayList<>();
    list.add(199);
    list.add(200);
    list.add(201);
    int res = studentDao.deleteSomeStudent(list);
    System.out.println("update some res = " + res);
    sqlSession.close();
}

lic void test08() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student s1 = new Student(199, “李一111”, “男”, null, “1111”, “li1.jpg”);
Student s2 = new Student(200, “李二222”, “男”, null, “1111”, “li2.jpg”);
Student s3 = new Student(201, “李三333”, “男”, null, “1111”, “li3.jpg”);
List list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
int res = studentDao.updateSomeStudent(list);
System.out.println("update some res = " + res);
sqlSession.close();
}

@Test
public void test09() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List list = new ArrayList<>();
list.add(199);
list.add(200);
list.add(201);
int res = studentDao.deleteSomeStudent(list);
System.out.println("update some res = " + res);
sqlSession.close();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/442886.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7.6部署ELK集群(二)之kibana7.7.0集群部署

32.4. 部署kibana7.7.0&#xff08;在主节点上操作&#xff09; 32.3.13. 下载kibana curl -L -O https://artifacts.elastic.co/downloads/kibana/kibana-7.7.0-linux-x86_64.tar.gz 32.3.14. 解压至安装目录 tar –xvf kibana-7.7.0-linux-x86_64.tar.gz -C /vmdata/ 32.…

【极简】windows下,vuejs打包,用Nginx部署http服务

做法 如果你熟悉vue&#xff0c;一般要“运行”会在目录用npm run dev&#xff0c;但是npm run dev 命令只用做本地调试&#xff0c;共开发者预览页面。 同部署到服务器供其他终端访问是不同的&#xff0c;如果要提供给其他浏览器或终端使用&#xff0c;则需要部署到具体的服…

算法记录 | Day34 贪心算法

1005.K次取反后最大化的数组和 class Solution:def largestSumAfterKNegations(self, A: List[int], K: int) -> int:A sorted(A, keyabs, reverseTrue) # 将A按绝对值从大到小排列for i in range(len(A)):if K > 0 and A[i] < 0:A[i] * -1K - 1if K > 0:A[-1] *…

FPGA双口RAM使用

模块名称&#xff1a; dpram() IP Core 双口RAM&#xff0c;有俩组数据线和地址线&#xff0c;读写可以同时进行&#xff0c;FIFO读写可以同时进行&#xff0c;可以看作是双口。分为Simple two-dual RAM和true two-dual RAM。简单双口RAM&#xff0c;一个端口只读&#xff0c;…

new、delete和malloc、free

C内存 图片来源阿秀的学习笔记 栈&#xff1a;函数内局部变量可以存储在栈区&#xff0c;函数执行结束自动释放。栈区内区分配运算内置于处理器指令集中堆&#xff1a;new分配的内存块&#xff0c;由应用程序控制自由存储区&#xff1a;和堆比较像&#xff0c;但是不等价全局…

406. 根据身高重建队列

假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造并返回输入数组 peopl…

生成与指定数组具有相同形状的全1数组np.ones_like()方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 生成与指定数组A形状相同的全1数组 np.ones_like() 选择题 关于以下代码说法错误的一项是? import numpy as np a np.array([[0,1],[2,3]]) print("【显示】a\n",a) print(&qu…

九龙证券|293份一季报预告逾七成预喜 机械设备等赛道业绩亮眼

2023年一季报预告正在连续出炉。Choice数据显现&#xff0c;截至4月17日21时&#xff0c;已有293家上市公司发布2023年一季报预告&#xff0c;按估计完成归母净利润同比变化幅度上限来看&#xff0c;其间有219家公司成绩预喜&#xff0c;占比约74.74%。分职业来看&#xff0c;机…

List

1.基本概念 功能: 将数据进行链式存储 链表(list) 是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成: 链表由一系列结点组成 结点的组成: 一个是存储数据元素的数据域&#xff0c;另一个是存储下一个结点地址的…

18.生命周期

目录 1 开启生命周期 2 创建前 beforeCreate() 3 创建后 created() 4 渲染前 beforeMount() 5 渲染后 mounted 6 更新渲染前 beforeUpdate() 7 更新渲染后 updated() 8 移除前 beforeUnmount() 9 移除后 unmounted() 生命周期是指 一个组件从创建->运行-&…

linux安装和使用jekins

Jenkins详细安装配置部署--超详细_jenkins安装部署_宝贝富贵猪的博客-CSDN博客 1.安装JDK 2.获取安装包 下载页面&#xff1a;https://jenkins.io/zh/download/ 或者Index of /jenkins/redhat/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 3.安装Jenkins sud…

深入理解Android布局:ConstraintLayout和RecyclerView的使用

深入理解Android布局&#xff1a;ConstraintLayout和RecyclerView的使用 I. 引言 介绍Android中布局的重要性 提出使用ConstraintLayout和RecyclerView布局的目的和意义 II. ConstraintLayout的使用 介绍ConstraintLayout的基本概念和特点 详细介绍ConstraintLayout的各种属性…

Spring Cloud微服务架构组件【Java培训】

SpringCloud是一系列框架的有序集合&#xff0c;为开发人员构建微服务架构提供了完整的解决方案。Spring Cloud根据分布式服务协调治理的需求成立了许多子项目&#xff0c;每个项目通过特定的组件去实现&#xff0c;下面我们讲解一下Spring Cloud 包含的常用组件以及模块。 (1…

【工业智能】需要了解的知识

【工业智能】需要了解的知识 算法数据预测模型决策协同模型优化控制异常诊断 图像目标检测语义分割关键点检测图像匹配3D抓取度量学习异常检测6D姿态估计 工业自动化、物联网通信IOT工业自动化边缘计算 写在前面&#xff1a; 本文仅为自己记录&#xff0c;不具有指导意义。 算法…

软文推广:真实有效提升软文排名与收录的三大方法!

软文是一种具有良好传播效果的文体&#xff0c;可以通过在搜索引擎中排名靠前的方式&#xff0c;为品牌或企业带来更多曝光。但是&#xff0c;如何让软文在搜索引擎中得到更好的收录和排名呢&#xff1f;在本文中&#xff0c;我们将讨论如何提升软文的收录和排名&#xff0c;以…

【DNS域名解析服务】

目录 一、DNS系统的作用DNS的介绍1.1、通用的顶级域名 二、DNS域名解析&#xff08;面试题&#xff09;三、DNS查询方式递归查询迭代查询 四、构建DNS域名服务器步骤4.1、安装bind软件包4.2、修改配置文件4.3、域名的配置修改区域配置文件&#xff0c;添加正向区域配置 4.4、覆…

Canokey Pigeon的初级玩法

Canokey Pigeon的初级玩法 前言开箱使用控制台新版旧版 初步设置FIDO2 PIN更改重置 坑&#xff08;或者说不满意的地方&#xff09;玩法FIDO2/U2FOpenPGPPIVNDEFOATH 参考 本文转载于我的博客Canokey Pigeon的初级玩法 Canokey Pigeon今天终于到货了 {% note warning flat %} …

【C++缺省参数、函数重载详解】

目录 一、缺省参数1.1缺省参数的定义1.2缺省参数的分类1.3缺省参数使用时的注意事项 二、函数重载2.1函数重载的概念2.2为什么要有函数重载2.3 C支持函数重载的原理 一、缺省参数 1.1缺省参数的定义 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&a…

搭建B2B2C多用户国际版商城系统,快速为外贸企业开拓新市场

企业市场竞争激烈&#xff0c;不只体现在国内&#xff0c;甚至全球&#xff0c;电商行业发展迅速&#xff0c;各企业各行业甚至进出口都竞争相当激烈。要想在这种告诉竞争中脱颖而出&#xff0c;开拓新市场&#xff0c;带来新盈利与新契机是必不可少的。易族智汇Javashop助力企…

nmap学习笔记

一、环境准备 Windows10主机Kali虚拟机&#xff08;使用nmap的地方&#xff09;metasploitable虚拟机为以上三个操作系统配置静态IP。 Windows主机的IP&#xff1a;192.168.80.3Kali的IP&#xff1a;192.168.80.2metasploitable的IP&#xff1a;192.168.80.4 具体配置方法请参…