Mybatis【适用于初学者】

MyBatis

什么是MyBatis框架

MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 JDBC,开发者只需要关注 sql 语句本身,

而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。

MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,

并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,

最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

框架是什么

框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;

另一种认为,框架是可被应用开发者定制的应用骨架、模板。

简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。

从另一个角度来说框架是一个舞台,你在舞台上做表演。在框架基础上加入你要完成的功能。

框架安全的,可复用的,不断升级的软件。

框架解决的问题

框架要解决的最重要的一个问题是技术整合。

框架把相关的技术融合在一起,企业开发可以集中在业务领

域方面。

另一个方面可以提供开发的效率。

JDBC编程的回顾

可以看之前总结的这篇博客

使用JDBC编程的缺点

  • 代码比较多,开发效率低
  • 需要关注 Connection ,Statement, ResultSet 对象的创建和销毁
  • 对 ResultSet 查询的结果,需要自己封装为 List
  • 重复的代码比较多
  • 业务代码和数据库的操作混在一起

MyBatis解决的主要问题

减轻使用 JDBC 的复杂性,不用编写重复的代码创建 Connetion , Statement ;

不用编写关闭资源代码。

直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳。

MyBatis 可以完成:

  1. 注册数据库的驱动,例如
Class.forName(“com.mysql.jdbc.Driver”))
  1. 创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象

  2. 从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象

List<Student> list = new ArrayLsit<>();
ResultSet rs = state.executeQuery(“select * from student”);
while(rs.next){
    
    
 Student student = new Student();
 student.setName(rs.getString(“name”));
 student.setAge(rs.getInt(“age”));
 list.add(student);
}
  1. 关闭资源
ResultSet.close() , Statement.close() , Conenection.close()

搭建MyBatis开发环境

  1. 建表

  2. 引入依赖【MyBatis依赖,Mysql驱动】

  3. 创建实体类【类的属性名要与表的列名一致】【表的每一行,都可以封装为一个对象】【面向对象的思想】

  4. 创建持久层的DAO接口

  5. 创建sql映射文件【写sql语句的,MyBatis会执行这些sql语句】,是一个xml文件。

    一般一个表一个sql映射文件。

  6. 创建MyBatis主配置文件,主配置文件提供了数据库的连接信息和slq映射文件的位置信息。

    一个项目就一个主配置文件。

具体搭建过程

  1. CREATE TABLE `student` (
     `id` int(11) NOT NULL ,
     `name` varchar(255) DEFAULT NULL,
     `email` varchar(255) DEFAULT NULL,
     `age` int(11) DEFAULT NULL,
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  2. <dependencies>
     <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.11</version>
     <scope>test</scope>
    </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.9</version>
     </dependency>
     </dependencies>
    
    <build>
     <resources>
     <resource>
     <directory>src/main/java</directory><!--所在的目录-->
     <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
     <include>**/*.properties</include>
     <include>**/*.xml</include>
     </includes>
     <filtering>false</filtering>
     </resource>
    </resources>
    </build>
    
  3. public class Student {
          
          
         //属性名和列名一样 
         private Integer id;
         private String name;
         private String email;
         private Integer age;
         // set , get , toString
    }
    
  4. public interface StudentDao {
          
          
         /*查询所有数据*/
         List<Student> selectStudents();
    }
    
  5. <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--
     namespace:必须有值,自定义的唯一字符串 
     推荐使用:dao 接口的全限定名称 
    --> <mapper namespace="com.xxx.dao.StudentDao">
     <!--
     <select>: 查询数据, 标签中必须是 select 语句
     id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称, 
     使用名称表示要执行的 sql 语句
     resultType: 查询语句的返回结果数据类型,使用全限定类名 
     -->
     <select id="selectStudents" resultType="com.xxx.entity.Student">
     <!--要执行的 sql 语句-->
         select id,name,email,age from student
     </select>
    </mapper>
    
  6. <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
     PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
     <!--配置 mybatis 环境-->
     <environments default="mysql">
     <!--id:数据源的名称-->
     <environment id="mysql">
     <!--配置事务类型:使用 JDBC 事务(使用 Connection 的提交和回滚)-->
     <transactionManager type="JDBC"/>
     <!--数据源 dataSource:创建数据库 Connection 对象
     type: POOLED 使用数据库的连接池 
     -->
     <dataSource type="POOLED">
     <!--连接数据库的四个要素-->
         <property name="driver" value="com.mysql.jdbc.Driver"/>
         <property name="url" value="jdbc:mysql://localhost:3306/student"/>
         <property name="username" value="root"/>
         <property name="password" value="123456"/>
     </dataSource>
     </environment>
     </environments>
         
     <mappers>
     <!--告诉 mybatis 要执行的 sql 语句的位置-->
         <mapper resource="com/xxx/dao/StudentDao.xml"/>
     </mappers>
    </configuration>
    
  7. @Test
    public void testMyBatis() throws IOException {
          
          
         //1.mybatis 主配置文件 
         String config = "mybatis-config.xml";
         //2.读取配置文件 
         InputStream in = Resources.getResourceAsStream(config);
         //3.创建 SqlSessionFactory 对象,目的是获取 SqlSession 
         SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
         //4.获取 SqlSession,SqlSession 能执行 sql 语句
         SqlSession session = factory.openSession();
         //5.执行 SqlSession 的 selectList()
         List<Student> studentList = 
         session.selectList("com.xxx.dao.StudentDao.selectStudents");//namespace + id
         //6.循环输出查询结果 
         studentList.forEach( student -> System.out.println(student));
         //7.关闭 SqlSession,释放资源
         session.close();
    }
    

MyBatis配置文件

  • dataSource 标签

    • dataSource 类型

      • UNPOOLED: 不使用连接池的数据源
      • POOLED: 使用连接池的数据源
      • JNDI: 使用 JNDI 实现的数据源

      其中 UNPOOLED ,POOLED 数据源实现了 javax.sq.DataSource 接口,

      JNDI 和前面两个实现方式不同,了解就可以。

    • dataSource 配置

      <dataSource type="POOLED">
           <!--连接数据库的四个要素-->
           <property name="driver" value="com.mysql.jdbc.Driver"/>
           <property name="url"  value="jdbc:mysql://localhost:3306/ssm?charset=utf-8"/>
           <property name="username" value="root"/>
           <property name="password" value="123456"/>
      </dataSource>
      
  • 事务

    • 默认需要手动提交事务

      • Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection对象的 commit(), rollback()

        Connection 对象的 setAutoCommit()方法来设置事务提交方式的。自动提交和手工提交。 -

      • <transactionManager type="JDBC"/>
        
      • JDBC:使用 JDBC 的事务管理机制。即通过 Connection 的 commit()方法提交,通过 rollback()方法回滚。

        但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对事务进行提交或回滚。

      • MANAGED:由容器来管理事务的整个生命周期(如 Spring 容器)

    • 自动提交事务

      • 设置自动提交的方式,factory 的 openSession() 分为有参数和无参数的。

        有参数为 true,使用自动提交 session = factory.openSession(true)

  • 使用数据库属性配置文件【properties文件】(解耦合

    • 为了方便对数据库连接的管理,DB 连接四要素数据一般都是存放在一个专门的属性文件中的。MyBatis主配置文件需要从这个属性文件中读取这些数据。

      • classpath 路径下,创建 properties 文件

        • 在 resources 目录创建 jdbc.properties 文件,文件名称自定义。

        • jdbc.driver=com.mysql.jdbc.Driver
          jdbc.url=jdbc:mysql://localhost:3306/ssm?charset=utf-8
          jdbc.username=root
          jdbc.password=root
          
      • 使用 properties 标签

        • <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE configuration
           PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
           "http://mybatis.org/dtd/mybatis-3-config.dtd"> 
          <configuration>
              <--!使用properties标签--/>
              <properties resource="jdbc.properties" />
          
      • 使用 key 指定值

        • <dataSource type="POOLED">
              <!--连接数据库的四个要素-->
              <property name="driver" value="${jdbc.driver}"/>
              <property name="url" value="${jdbc.url}"/>
              <property name="username" value="${jdbc.username}"/>
              <property name="password" value="${jdbc.password}"/>
          </dataSource>
          
  • mappers【映射器】

    • < mapper resource=" " />

      • 使用相对于类路径的资源,从 classpath 路径查找文件

    • < package name=""/>

      • 指定包下的所有 Dao 接口

      • 注意:此种方法要求 Dao 接口名称和 mapper 映射文件名称相同,且在同一个目录中。

MyBatis 使用传统 Dao 开发方式

创建工具类

public class MyBatisUtil {
    
    
 	//定义 SqlSessionFactory
 	private static SqlSessionFactory factory = null;
 	static {
    
    
 	//使用 静态块 创建一次 SqlSessionFactory
 	try{
    
    
 		String config = "mybatis-config.xml";
 	//读取配置文件 
 		InputStream in = Resources.getResourceAsStream(config);
	 //创建 SqlSessionFactory 对象 
 		factory = new SqlSessionFactoryBuilder().build(in);
 	} catch (Exception e){
    
    
 		factory = null;
 		e.printStackTrace();
	}
 }
	 /* 获取 SqlSession 对象 */
 	public static SqlSession getSqlSession(){
    
    
 		SqlSession session = null;
 		if( factory != null){
    
    
 			session = factory.openSession();
 		}
 		return session;
 	} 
}

DAO开发

1)创建 Dao 接口实现类
public class StudentDaoImpl implements StudentDao2)实现接口中 select 方法
public List<Student> selectStudents() {
    
    
    SqlSession session = MyBatisUtil.getSqlSession();
    List<Student> studentList = session.selectList(
        "com.xxx.dao.StudentDao.selectStudents");
    session.close();
    return studentList;
}

测试查询操作:
// MyBatisTest 类中创建 StudentDaoImpl 对象
public class MyBatisTest {
    
    
@Test
public void testSelect() throws IOException {
    
    
    StudentDao studentDao = new StudentDaoImpl(); 
    List<Student> studentList = studentDao.selectStudents();
    studentList.forEach( stu -> System.out.println(stu));
}

传统 Dao 开发方式的分析

在前面例子中自定义 Dao 接口实现类时发现一个问题:

Dao 的实现类其实并没有干什么实质性的工作,

它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,

真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。

所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,

对DB 进行操作。
这种对 Dao 的实现方式称为 Mapper 的动态代理方式。

Mapper 动态代理方式无需程序员实现 Dao 接口。

接口是由 MyBatis 结合映射文件自动生成的动态代理实现的。

MyBatis动态代理

我们不再需要编写DAO接口的实现类,只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定 Dao接口类的 class 值。

StudentDao studentDao = MyBatisUtil.getSqlSession().getMapper(StudentDao.class);

使用DAO代理对象执行sql语句

select 方法:
@Test
public void testSelect() throws IOException {
    
    
     List<Student> studentList = studentDao.selectStudents();
     studentList.forEach( stu -> System.out.println(stu));
}
insert 方法:
@Test
public void testInsert() throws IOException {
    
    
     Student student = new Student();
     student.setId(1006);
     student.setName("林浩");
     student.setEmail("[email protected]");
     student.setAge(26);
     int nums = studentDao.insertStudent(student);
     System.out.println("使用 Dao 添加数据:"+nums);
}
update 方法
@Test
public void testUpdate() throws IOException {
    
    
     Student student = new Student();
     student.setId(1006);
     student.setAge(28);
     int nums = studentDao.updateStudent(student);
     System.out.println("使用 Dao 修改数据:"+nums);
}
delete 方法
@Test
public void testDelete() throws IOException {
    
    
     int nums = studentDao.deleteStudent(1006);
     System.out.println("使用 Dao 修改数据:"+nums);
}

原理

这里解释了上面为什么要推荐namespace的值写为: dao接口的全限定名称

id的值写为:dao 接口中方法名称

只有这样MyBatis才能准确的知道你要执行的sql语句是什么

JDK的动态代理

深入理解参数

parameterType

接口中的方法参数的类型, Java的数据类型的全限定名称或MyBatis定义的别名。

这个属性是可选的,因为 MyBatis通过反射机制能够发现接口方法参数的类型。

MyBatis 传递参数

一个简单类型的参数:

简单类型:MyBatis把基本数据类型和String都叫做简单类型。

使用:#{任意字符},和方法的参数无关。

使用#{}之后,MyBatis执行sql语句使用的是PreparedStatement对象。

关于PreparedStatement对象的使用,可以看这篇博客

多个参数:

  • 使用@param

在方法形参前面加入@Param(“自定义参数名”),mapper 文件使用#{自定义参数名}。

接口方法:
List<Student> selectMultiParam(@Param("personName") String name,
@Param("personAge") int age);
mapper 文件:
<select id="selectMultiParam" resultType="com.xxx.domain.Student">
     select id,name,email,age from student where name= #{personName} or 
     age= #{personAge}
</select>
  • 使用对象

使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。

语法格式: #{ property, javaType=java 中数据类型名, jdbcType=数据类型名称 }

javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格式 #{ property 【对象的属性名】}

  • 按位置(了解)

参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0}, 第二个是#{arg1}

注意:mybatis-3.3 版本和之前的版本使用#{0},#{1}方式, 从 mybatis3.4 开始使用#{arg0}方式。

  • 使用Map(了解)

Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key,

Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值。

例如:
Map<String,Object> data = new HashMap<String,Object>();
data.put(“myname”,”xxx");
data.put(“myage”,20);
接口方法:
List<Student> selectMultiMap(Map<String,Object> map);
mapper 文件:
<select id="selectMultiMap" resultType="com.xxx.domain.Student">
     select id,name,email,age from student where name=#{myname} or age =#{myage}
</select>

**#**和$

#:占位符,告诉 mybatis 使用实际的参数值代替。并使用PrepareStatement对象执行 sql 语句,

#{…}代替sql 语句的“?”。这样做更安全【能避免sql注入】,更迅速,效率高,通常也是首选做法。

** ∗ ∗ 【 ∗ ∗ 字 符 串 替 换 ∗ ∗ 】 : 告 诉 m y b a t i s 使 用 ** 【**字符串替换**】:告诉 mybatis 使用 mybatis使包含的"字符串"替换所在位置。使用Statement把sql语句

和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。

但是具有sql注入的风险。详见这篇博客

封装 MyBatis 输出结果

定义别名

<--!在mybatis.xml主配置文件定义别名-->
<typeAliases>
 <!--
 第一种方式:定义单个类型的别名
 type:类型的全限定名称
 alias:自定义别名 
 -->
     <typeAlias type = "com.xxx.domain.Student" alias = "mystudent"/>
 <!--
 第二种方式:批量定义别名,扫描整个包下的类,别名为类名(首字母大写或小写都可以)
 name:包名 
 -->
     <package name ="com.xxx.domain"/>
     <package name ="...其他包"/>
</typeAliases> 

resultType

执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。 注意如果返回的是集合,

那应该设置为集合中的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。

  • 简单类型
// 接口方法:
int countStudent();
mapper 文件:
<select id="countStudent" resultType="int">
     select count(*) from student
</select>
// 测试方法:
@Test
public void testRetunInt(){
    
    
     int count = studentDao.countStudent();
     System.out.println("学生总人数:"+ count);
}
  • 对象类型

    • 处理方法:
      • MyBatis执行sql语句,然后调用类的无参构造方法,创建对象。
      • MyBatis把ResultSet指定的列值赋值给同名的属性名。
  • Map

sql 的查询结果作为 Map 的 key 和 value。推荐使用 Map<Object,Object>。

注意:Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录是错误。

resultMap

resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。

常用在列名和 java 对象属性名不一样的情况。

使用方式:

1.先定义 resultMap,指定列名和属性的对应关系。

2.在中把 resultType 替换为 resultMap。

列名和属性名不一样的解决方案

第一 种方式:使用resultMap
public class PrimaryStudent {
    
    
     private Integer stuId;
     private String stuName;
     private Integer stuAge;
     // set , get 方法
}
<!-- 创建 resultMap
     id:自定义的唯一名称,在<select>使用
     type:期望转为的 java 对象的全限定名称或别名 
--> 
<resultMap id="primaryStudentMap" type="com.bjpowernode.domain.PrimaryStudent">
     <!-- 主键字段使用 id -->
     <id column="id" property="stuId" />
     <!--非主键字段使用 result-->
     <result column="name" property="stuName"/>
     <result column="age" property="stuAge" />
</resultMap>

<!--resultMap: resultMap 标签中的 id 属性值--> 
<select id="selectUseDiffResultMap" resultMap="primaryStudentMap">
     select id,name,email,age from student
</select>
第二种方式:使用列别名
<select id="selectUseFieldAlias" resultType="com.bjpowernode.domain.PrimaryStudent">
     select id as stuId, name as stuName,age as stuAge from student 
</select>

模糊查询like

模糊查询的实现有两种方式, 一是 java 代码中给查询数据加上“%” ; 推荐

二是在 mapper 文件 sql 语句的条件位置加上“%”

方法一:

// 需求:查询姓名有“力”的
// 接口方法:
List<Student> selectLikeFirst(String name);
mapper文件:
<select id="selectLikeFirst" resultType="com.bjpowernode.domain.Student">
     select id,name,email,age from student
     where name like #{
    
    studentName}
</select>
// 测试方法:
@Test
public void testSelectLikeOne(){
    
    
     String name="%力%";
     List<Student> stuList = studentDao.selectLikeFirst(name);
     stuList.forEach( stu -> System.out.println(stu));
}

方法二:

// 接口方法:
List<Student> selectLikeSecond(String name);
mapper 文件:
<select id="selectLikeSecond" resultType="com.bjpowernode.domain.Student">
     select id,name,email,age from student
     where name like "%" #{
    
    studentName} "%"
</select>
// 测试方法:
@Test
public void testSelectLikeSecond(){
    
    
     String name="力";
     List<Student> stuList = studentDao.selectLikeSecond(name);
     stuList.forEach( stu -> System.out.println(stu));
}

动态sql

动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。

提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,

将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题

动态 SQL 之< if >

对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。
语法:< if test=“条件” > sql 语句的部分 < /if >

<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
     select id,name,email,age from student
     where 1=1
     <if test="name != null and name !='' ">
     and name = #{name}
     </if>
     <if test="age > 0 ">
     and age &gt; #{age}
     </if>
</select>

动态 SQL < where >

< if/ >标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。

因为,若 where 后的所有< if/ >条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL出错。

所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。

使用< where/ >标签,在有查询条件时,可以自动添加上 where 子句;

没有查询条件时,不会添加where 子句。需要注意的是,第一个< if/ >标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,

系统会将多出的 and 去掉。但其它< if/ >中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错

语法:< where > 其他动态 sql < /where >

<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
     select id,name,email,age from student
 <where>
     <if test="name != null and name !='' ">
     and name = #{name}
     </if>
     <if test="age > 0 ">
     and age &gt; #{age}
     </if>
 </where>
</

动态 SQL < foreach >

< foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意:

➢ collection 表示要遍历的集合类型, list ,array 等。

➢ open、close、separator 对遍历内容的 SQL 拼接。

语法:
<foreach collection="集合类型" open="开始的字符" close="结束的字符" 
    item="集合中的成员" separator="集合成员之间的分隔符">
     #{item 的值}
</foreach>
遍历 **List<**简单类型>
// 需求:查询学生 id 是 1002,1005,1006 
// 接口方法:
List<Student> selectStudentForList(List<Integer> idList);
// mapper 文件:
<select id="selectStudentForList" resultType="com.xxx.domain.Student">
 	select id,name,email,age from student
 <if test="list !=null and list.size > 0 ">
 	where id in
     <foreach collection="list" open="(" close=")" item="stuid" separator=",">
        #{
    
    stuid}
     </foreach>
 </if>
</select>
// 测试方法:
@Test
public void testSelectForList() {
    
    
     List<Integer> list = new ArrayList<>();
     list.add(1002);
     list.add(1005);
     list.add(1006);
     List<Student> studentList = studentDao.selectStudentForList(list);
     studentList.forEach( stu -> System.out.println(stu));
}
遍历 **List<**对象类型>
// 接口方法:
List<Student> selectStudentForList2(List<Student> stuList);
// mapper 文件:
<select id="selectStudentForList2" resultType="com.xxx.domain.Student">
 	select id,name,email,age from student
 <if test="list !=null and list.size > 0 ">
	 where id in
     <foreach collection="list" open="(" close=")" item="stuobject" separator=",">
    	 #{
    
    stuobject.id}
     </foreach>
 </if>
</select>

// 测试方法:
@Test
public void testSelectForList2() {
    
    
     List<Student> list = new ArrayList<>();
     Student s1 = new Student();
     s1.setId(1002);
     list.add(s1);
     s1 = new Student();
     s1.setId(1005);
     list.add(s1);
     List<Student> studentList = studentDao.selectStudentForList2(list);
     studentList.forEach( stu -> System.out.println(stu));
}

动态 SQL 之代码片段

< sql/ >标签用于定义 SQL 片段,以便其它 SQL 标签复用。

而其它标签使用该 SQL 片断,需要使用< include/ >子标签。

该< sql/ >标签可以定义 SQL 语句中的任何部分,所以< include/ >子标签可以放在动态 SQL的任何位置。

<!--创建 sql 片段 id:片段的自定义名称--> 
<sql id="studentSql">
 select id,name,email,age from student
</sql> 

<select id="selectStudentSqlFragment" resultType="com.xxx.domain.Student">
 <!-- 引用 sql 片段 -->
 <include refid="studentSql"/>
 <if test="list !=null and list.size > 0 ">
 	where id in
     <foreach collection="list" open="(" close=")" item="stuobject" separator=",">
     	#{stuobject.id}
     </foreach>
 </if>
</select>

PageHelper

基于 PageHelper 分页:

实现步骤:

1)Maven坐标:

<dependency>
 <groupId>com.github.pagehelper</groupId>
 <artifactId>pagehelper</artifactId>
 <version>5.1.10</version>
</dependency> 

2)加入plugin配置

<environments>之前加入
<plugins>
 <plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>

3)PageHelper 对象

查询语句之前调用 PageHelper.startPage 静态方法。

除了 PageHelper.startPage 方法外,还提供了类似用法的 PageHelper.offsetPage 方法。

在你需要进行分页的 MyBatis 查询方法前调用 PageHelper.startPage 静态方法即可,紧跟在这个

方法后的第一个 MyBatis 查询方法会被进行分页。

@Test
public void testSelect() throws IOException {
    
    
	// 获取第1页,3条内容。
    PageHelper.startPage(1, 3);
    List<Student> studentList = studentDao.selectSAtudents();
    studentList.forEach(stu -> System.out.println(stu));
}

猜你喜欢

转载自blog.csdn.net/Sherlook_Holmes/article/details/122461391