MyBatis学习笔记

MyBatis官方文档

1.框架概述

MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

1.1 目前一般采用以下三层架构

  • 界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。在实现代码中,界面层的代码一般放置于controller包中。
  • 业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据。在实现代码中,业务逻辑层的代码一般放置于service包中(XXXService类)。
  • 数据访问层(持久层): 就是访问数据库, 执行对数据的查询,修改,删除等等的。在实现代码中,数据访问层的代码一般放置于dao包中(XXXDao类)。

1.2 三层中各个类的交互方式

用户使用界面层 --> 业务逻辑层 ---> 数据访问层(持久层)--> 数据库(mysql)

1.3 三层对应的处理框架

  • 界面层---springmvc(框架)
  • 业务逻辑层---service类--spring(框架)
  • 数据访问层---dao类--mybatis(框架)

这三层对应的框架便是非常著名的SSM三件套。利用SpringMVC接收用户请求,响应结果。利用Spring管理service类。利用mybatis代替jdbc访问数据库,所以mybatis可以看成是功能更加完善的jdbc。

1.4 三个框架简介

MyBatis框架:
MyBatis是一个优秀的基于java的持久层框架,内部封装了jdbc,开发者只需要关注sql语句本身,而不需要处理加载驱动、创建连接、创建statement、关闭连接,资源等繁杂的过程。MyBatis通过xml或注解两种方式将要执行的各种sql语句配置起来,并通过java对象和sql的动态参数进行映射生成最终执行的sql语句,最后由 mybatis框架执行sql并将结果映射为java对象并返回。开发人员使用MyBatis的流程如下:
开发人员提供sql语句 ---> mybatis处理sql ---> 开发人员得到List集合或java对象(表中的数据)

Spring框架:
Spring框架为了解决软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前非常复杂的企业级开发。Spring解决了业务对象,功能模块之间的耦合,不仅在javase,web中使用,大部分Java应用都可以从Spring中受益。Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器。

SpringMVC框架
SpringMVC属于SpringFrameWork 3.0 版本加入的一个模块,为Spring框架提供了构建Web应用程序的能力。现在可以Spring框架提供的SpringMVC模块实现web应用开发,在web项目中可以无缝使用Spring和SpringMVC框架。

1.5 MyBatis功能

MyBatis是一个sql映射框架,提供对数据库的操作能力。可以理解为是增强的JDBC。其主要有两个功能

  • sql mapper:sql映射功能,可以把数据库表中的一行数据映射为一个java对象。操作这个对象,就相当于操作表中的数据
  • Data Access Objects(DAOs) : 数据访问功能, 可以对数据库进行增删改查等操作。

2.MyBatis框架快速入门

2.1 MyBatis查询数据库操作

MyBatis的基本使用步骤如下:

  • 1.在数据库中新建student表

  • 2.在Maven中加入mybatis和mysql的相关依赖

    •      <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-tx</artifactId>
              <version>5.3.8</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-jdbc</artifactId>
              <version>5.3.8</version>
          </dependency>
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.5.7</version>
          </dependency>
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis-spring</artifactId>
              <version>2.0.6</version>
          </dependency>
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>8.0.25</version>
          </dependency>
          <dependency>
              <groupId>com.alibaba</groupId>
              <artifactId>druid</artifactId>
              <version>1.2.1</version>
          </dependency>
      
  • 3.创建实体类:student,用于保存数据库中student表中对应的一行数据。一般实体类在实现代码中都放在entity包中。

  • 4.创建持久层的dao接口,定义操作数据库的方法(只需要声明方法即可)

    • package com.sysu.dao;
      import com.sysu.entity.Student;
      
      import java.util.List;
      public interface StudentDao {
          public List<Student> selectStudents();
      }
      
  • 5.创建一个mybatis使用的配置文件:sql映射文件(一个xml文件,文件内容如下),然后在映射文件中写sql语句,一般一个表对应一个sql映射文件。

    • xml文件应该创建在接口所在的目录中,同时最好保证文件名称和接口名字一致。

    • <!--
          sql映射文件:用于写sql语句的,mybatis会执行这些sql语句。
          1.指定约束文件
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd"
              mybatis-3-mapper.dtd是约束文件的名称,扩展名为dtd。
          2.约束文件的作用:
              限制并检查在当前文件中出现的标签和属性必须是要符合Mybatis的要求。
          3.<mapper>为当前文件的跟标签,是必须存在的。
            namespace:命名空间,namespace对应的值必须使用dao接口的全限定名称
            <mapper namespace="dao接口对应的全限定名称">
      
          4.在xml文件中,可以使用特定的标签来表示数据库中的特定操作。
            <select>:表示执行查询操作
              <select id = "接口中对应的方法名称" resultType="sql语句执行结果的对象类型对应的全限定名称">
            <update>:表示更新数据库的操作
            <insert>:表示插入
            <delete>:表示删除
      
          5.namespace与id就是帮助MyBatis框架定位sql语句对应的方法,所以需要使用dao接口的全限定名。
      -->
      
      <?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">
      <mapper namespace="com.sysu.dao.StudentDao">
          <select id="selectStudents" resultType="com.sysu.domain.Student">
              select id,name,email,age from student order by id
          </select>
      </mapper>
      
  • 6.创建mybatis的主配置文件:主配置文件提供了数据库的连接信息和sql映射文件的位置信息,一般一个项目对应一个主配置文件。配置文件内容如下:

    • <!--
          MyBatis的主配置文件:主要定义数据库的配置信息以及sql映射文件的位置
          1.约束文件
              <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
              mybatis-3-config.dtd约束文件的名称
          2.<configuration>根标签,该标签通常包括两部分:
              <environments>:数据库的连接信息
              <mappers>:sql映射文件的位置(相对于main/java而言)
      -->
      
      <?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>
      <!--    environments是复数,表示可以管理多个数据库的连接信息,所以default的值必须与其中一个的<environment id="">相同-->
          <environments default="development">
              <environment id="development">
                  
                  <transactionManager type="JDBC"/>
      <!--    transactionManager用于定义提交事务、回滚事务的方式。type有两种取值:
      		(1)JDBC:表示mybatis底层调用JDBC中的Connection对象进行事务的处理
      		(2)MANAGED:将mybatis的事务处理委托给其他容器(例如spring等)-->
                  
                  <dataSource type="POOLED">
      <!--    type:指定数据连接的类型
      		(1)POOLED:使用连接池
      		(2)UNPOOLED:不使用连接池,每次执行sql语句都新建连接,执行完sql语句后在关闭连接。-->
                      <property name="driver" value="com.mysql.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                      <property name="username" value="root"/>
                      <property name="password" value="123456"/>
                      <!-- 通常情况下需要把数据库的连接信息放到一个单独的文件中,这个文件一般称为属性配置文件。-->  
                  </dataSource>
              </environment>
          </environments>
          
          <mappers>
              <!-- 相对于main/java 以及 main/resouces的路径 --> 
              <!-- https://www.cnblogs.com/zhangxiaolei0/p/14370656.html --> 
              <mapper resource="com/sysu/dao/StudentDao.xml"/>
          </mappers>
      </configuration>
      
  • 7.获取SqlSession对象,通过它的方法执行sql语句。

    • public class myapp {
          public static void main(String[] args) throws IOException {
              //1.定义mybatis主配置文件的名称,从类路径开始(target/classes),如果target/classes路径下没有mybatis.xml,则说明mvn compile命令执行不完善,可以手动将mybatis.xml文件复制一份到target/classes目录下。
              //通常情况下都会把12345这五个步骤封装至utils中。
              String config = "mybatis.xml";
              //2.读取config表示的文件
              InputStream in = Resources.getResourceAsStream(config);
              //3.创建SqlSessionFactoryBuilder对象
              SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
              //4.创建SqlSessionFactory对象
              SqlSessionFactory factory = builder.build(in);
              //5.从SqlSessionFactory对象中获取SqlSession对象,可以根据openSession()传入的参数自定义是否自动提交事务,openSession(true)表示自动提交事务。
              SqlSession sqlSession = factory.openSession();
              
              //67本质是StudentDao接口中selectStudents()方法的实现,该部分代码在后期可以省略,因为根据MyBatis动态代理可以达到同样的效果。
              //6.【自定义】指定要执行的sql语句标识
              String sqlId = "com.bjpowernode.dao.StudentDao.selectStudents";
              //7.【自定义】执行sql语句,得到执行结果
              List<Student> studentList = sqlSession.selectList(sqlId);
              for(Student st : studentList) System.out.println(st);
              sqlSession.close();
              //上述代码执行查询操作,当执行insert、update、delete等操作时候一定要主动提交事务,否则数据库中的数据不改变.
              //sqlSession.commit();
       ------------------------------------------------------------------------------
              
              //动态代理的实现方式如下:
              //StudentDao dao = sqlSession.getMapper(StudentDao.class);
              //List<Student> students = dao.selectStudents();
              //for(Student student : students) System.out.println(student);
          }
      }
      

第七个步骤 “获取SqlSession对象,通过它的方法执行sql语句",该步骤有两种实现方式:

  • 传统Dao开发模式:实现StudentDao接口中的方法,并使用这些方法对数据库进行操作。
  • MyBatis动态代理模式(必须掌握):MyBatis动态代理可以让我们省去实现StudentDao接口中的方法这一步骤,它会直接定位到映射文件 mapper 中的相应 SQL 语句,对DB进行操作。底层是通过反射进行实现的。
//动态代理的实现方式如下:
获取SqlSession对象
SqlSession sqlSession = factory.openSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectStudents();
for(Student student : students) System.out.println(student);

2.2 MyBatis Insert操作(使用动态代理)

MyBatis初始化的时候比较麻烦,日后在和数据库打交道就比较简单了。

  • 1.在dao接口中定义操作数据库的方法(只需要声明方法即可)
package com.sysu.dao;
import com.sysu.entity.Student;
import java.util.List;

public interface StudentDao {
    public List<Student> selectStudents();
    //定义insert插入方法,该方法只有一个参数Student,所以在sql映射文件中不需要写parameterType=”“参数
    //如果方法中有多个参数需要使用@Param命名参数(见3.3.2)
    public int insertStudent(Student student);
}
  • 2.在sql映射文件中写sql语句。
<?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">
<mapper namespace="com.sysu.dao.StudentDao">
    <select id="selectStudents" resultType="com.sysu.entity.Student">
        select id,name,email,age from student order by id
    </select>
	
    <insert id="insertStudent">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
</mapper>
  • 3.获取SqlSession对象,通过MyBatis动态代理实现对数据库的访问与操作。
package com.sysu;
import com.sysu.entity.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class myapp {
    public static void main(String[] args) throws IOException {
        //通常把下面4个步骤封装至utils包中,用于获取SqlSession对象
        String config = "mybatis.xml";
        InputStream in = Resources.getResourceAsStream(config);
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
     	
        //获取SqlSession对象
        SqlSession sqlSession = factory.openSession();

        //创建需要插入的student对象
        Student student = new Student();
        student.setId(1003);
        student.setName("王五");
        student.setEmail("ddd@qq");
        student.setAge(35);
        
        //Mybatis动态代理
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        int ans = dao.insertStudent(student);
        System.out.println(ans);
    }
}

3.MyBatis框架Dao代理(※)

3.1 实现步骤

实现步骤见2.1和2.2。或者见下图

3.2 实现原理

动态代理。

有关动态代理的内容见链接:动态代理

https://www.cnblogs.com/jia0504/p/13811424.html

3.3 MyBatis相关参数的理解

(1)parameterType

<?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">
<mapper namespace="com.sysu.dao.StudentDao">
    
    <select id="selectStudentById" parameterType="int" resultType="com.sysu.entity.Student">
        select id,name,email,age from student where id = #{id}
    </select>
    
</mapper>

parameterType表示StudentDao接口中方法参数的数据类型。parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数据类型。所以可以没有。一般我们也不写。

例如StudentDao接口中存在方法:public Student selectStudentById(Integer id),则 parameterType="int"

在sql映射文件中,可以通过#{“任意字符”}获取简单类型的一个参数的值。例如通过#{id}获取selectStudentById(Integer id)方法中传入的id值。
实现原理如下:首先需要知道MyBatis就是对JDBC的一个封装
(1) MyBatis创建Connection以及PreparedStatement对象
	String sql = “select id,name,email,age from student where id = ?”
	PreparedStatement pst = conn.preparedStatement(sql);
	// 一个问好就相当于一个占位符,setInt传入第一个参数
	pst.setInt(1,1001);
	
(2) 执行sql封装为Student对象。
    Resultset rs = ps.executeouery();student student = null;
    while(rs.next()){
    	//从数据库取表的一行数据,存到一个java对象属性中ltudent = new student();
    	student.setId(rs.getInt("id));
    	student.setName(rs.getstring( "name" ));
    	student.setEmail(rs.getstring( "email"));
    	student.setAge(rs.getInt("age"));
    }
    return sfudent;
当我们在sql映射文件中写sql语句时,底层的实现原理就如(1)(2)两个步骤,所以可以认为MyBatis就是对JDBC进行了封装。

(2)@Param命名参数

在sql映射文件中,有两种常用的方法可以获取多个参数的值。

  • @Param命名参数获取多个参数的值

    使用方法:在dao接口声明的方法中加入@Param(“自定义参数名称”),然后在sql映射文件使用#{“自定义参数名称”}。

    例如dao接口存在selectMulitParam()方法:
    步骤一:public List selectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
    步骤二:对应sql映射文件为:

  • 通过传递类型为Java对象的参数来获取多个参数的值(其实insert的sql语句就是采用这种方式)

使用方法:在dao接口声明的方法中加入Java对象,然后在sql映射文件使用#{“对象的属性名”}。
步骤一:public List<Student> selectMulitParam(Student)
步骤二:对应sql映射文件为:
<select>
	select * from student where name=#{name} or age=#{age}
</select>

3.4 #和$的区别

首先需要明白:在sql映射文件中无论是使用“#”还是“$",都能正常工作!!

#:占位符,告诉mybatis使用实际的参数值代替。并使用PrepareStatement对象执行sql语句,#{"自定义字符"}代替 sql 语句的“?”

这样做更安全,更迅速,通常也是首选做法。

sql映射文件
<select id="selectById" resultType = "com.sysu.entiy.Student">
    select id,name,email,age from student where id = #{studentId}
</select>

转为 MyBatis 的执行是: 

String sql=” select id,name,email,age from student where id = ?”; 
PreparedStatement ps = conn.prepareStatement(sql); 
ps.setInt(1,1005); 

where id=? 就是 where id = #{studentId} 
ps.setInt(1,1005) , 1005 会替换掉 #{studentId}

$:主要用于替换表名或者列名。具体实例如下:

1.dao接口文件中声明方法:
List<Student> selectUse$Order(@Param("colName") String colName);
    
2.sql映射文件写sql语句
<select id="selectUse$Order" resultType = "com.sysu.entiy.Student">
    select * from student order by ${colName}
</select>

3.MyBatis动态代理实现与数据库的交互
SqlSession sqlSession = MyBatisUtils.getSqlSesson();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
// 根据name这一列的属性值进行排序
List<Student> students = dao.selectUse$Order("name")

两者的区别如下:

1. #使用?在sql语句中做占位符, 使用PreparedStatement执行sql,效率高。能避免sql注入,更安全。
2. $不使用占位符,表示字符串的连接,使用Statement对象执行sql,效率低。有sql注入的风险,缺乏安全性。
3. $主要用于替换表名或者列名,一般在数据需要根据某个列属性进行排序的场景下使用。

3.5 MyBatis的输出结果

MyBatis的输出结果为Java对象,MyBatis通过使用resultType以及resultMap两种参数让MyBatis明白sql语句执行结果需要转换的对象类型。

(1) resultType

表示sql语句的执行结果需要转换的Java对象类型。

public Student selectStudentById(@Param("id") Integer id);

<!-- resultType=Student,表示sql语句的执行结果需要转换为Student对象 -->
<select id="selectStudentById" parameterType="int" resultType="com.sysu.entity.Student(Student类型的全限定名称)">
    select id,name,email,age from student where id = #{id}
</select>
  • resultType的值可以看成是dao接口中方法的返回类型。它的值有两种:1. 类型的全限定名称(推荐)。 2. 类型的别名, 例如 java.lang.Integer别名是int
  • 实现原理:把同名列的值赋给resultType中指定对象的同名属性,例如:查询结果id列的值赋给Student中的id属性,name列的值赋给Student中的name属性。这一过程是通过对象的get、set方法实现的,因此对象中一定要实现get、set方法。
public List<Student> selectStudents();
    
<select id="selectStudents" parameterType="int" resultType="com.sysu.entity.Student">
    select id,name,email,age from student
</select>
    
这种情况下resultType不能等于List,因为列值id,name,email,age这些是Student对象的属性,而不是List对象的属性。

(2) resultMap

MyStudent类的定义
class MyStudent{
	Integer Myid;
	String Myname;
	String Myemail;
	Integer Myage;
}

dao接口中定义的方法:public List<MyStudent> selectStudents();
    
sql映射文件:
<select id="selectStudents" parameterType="int" resultType="com.sysu.entity.MyStudent">
    select id,name,email,age from student
</select>

当列名(id,name,email,age)和对象中的属性名(Myid、Myname、Myemail、Myage)不一样时,使用resultType将会得到null的对象,解决方案:

  • 使用别名
修改sql映射文件
<select id="selectStudents" parameterType="int" resultType="com.sysu.entity.MyStudent">
    select id as Myid, name as Myname, email as Myemail, age as Myage from student
</select>
  • 使用resultMap

resultMap可以自定义sql执行结果的列名对象中的属性名之间映射关系。常用在列名和 java 对象属性名不一样的情况。

使用方式: 
1.在sql映射文件中定义resultMap,指定列名和属性的对应关系。
<!-- 创建 resultMap
 id:自定义的唯一名称,在<select>使用
 type:期望转为的 java 对象的全限定名称或别名 
-->
<resultMap id="MyStudentMap" type="com.sysu.entity.MyStudent">
 	<!-- 主键字段使用 id -->
    <!-- 将id列的值映射至对象中的Myid属性 -->
 	<id column="id" property="Myid" />
 	<!--非主键字段使用 result-->
    <!-- 将name列的值映射至对象中的Myname属性 -->
 	<result column="name" property="Myname"/>
    <result column="email" property="Myemail"/>
 	<result column="age" property="Myage" />
</resultMap>

2.在中把 resultType 替换为 resultMap。
<!--resultMap: resultMap 标签中的 id 属性值-->
<select id="selectUseDiffResultMap" resultMap="MyStudentMap">
 	select id,name,email,age from student where name=#{queryName} or age=#{queryAge}
</select>

3.6 like模糊查询

MyBatis有两种方式实现like模糊查询

  • 1. java代码中给查询数据加上“%” (最常用)
接口方法:
List<Student> selectLikeFirst(String name);

sql映射文件(mapper文件):
<select id="selectLikeFirst" resultType="com.sysu.entity.Student">
    <!-- #{}:表示dao接口中对应的方法需要传入一个参数 -->
 	select id,name,email,age from student where name like #{studentName}
</select>

测试方法:
@Test
public void testSelectLikeOne(){
    String name="%李%";
    List<Student> stuList = studentDao.selectLikeFirst(name);
    for(Student stu : stuList) ystem.out.println(stu);
}
  • 2.在mapper文件sql语句的条件位置加上“%”
接口方法:
List<Student> selectLikeSecond(String name);
    
mapper 文件:
<select id="selectLikeSecond" resultType="com.sysu.entity.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);
     for(Student stu : stuList) ystem.out.println(stu);
}

4.MyBatis框架动态SQL(※)

动态sql: sql的内容是变化的,可以根据条件获取到不同的sql语句。主要是where部分发生变化。MyBatis主要通过这三个常用标签实现动态sql:<if><where><foreach>

4.1 if 标签

<if>标签用于条件判断,当条件判断为true时,会将其包含的sql片段拼接到其所在的sql语句中。

<if test = "条件">
	部分sql语句
</if>


1.dao接口声明的方法如下:
public List<Student> selectStudentIf(Student student);
    
2.sql映射文件内容如下:
<!-- 
	<if test = "使用参数Java对象的属性值作为判断条件,所以要使用动态sql,dao接口方法中传入的参数必须是Java对象">
-->
<select id = "selectStudentIf" resultType = "com.sysu.entity.Student">
	select id,name,email,age from student
    where 1 = 1(防止出现语法错误)
    <if test = "name != null and name != ''">
        name = #{name}
    </if>
    <if test = "age > 0">
        or age > #{age}
    </if>
</select>

3.test测试
@Test
public void testSelectStudentIf(){
	SqlSession sqlSession = MyBatisUtils.getSqlSession();
    Student dao = sqlSession.getMapper(StudentDao.class);
    
    Student student = new Student();
    student.setName("abc");
    student.setAge(18);
    List<Student> students = dao.selectStudentIf(student);
    for(Student stu:students) System.out.println(stu);
}
此代码段的含义为:在数据中查找所有名字为“abc”或者年龄大于18的数据。

4.2 where标签

  • <if>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若where后的所有条件均为 false,而 where 后若又没有 1 = 1 子句,则 SQL 中就会只剩下一个空的 where,SQL出错。所以,在where后,需要添加永为真子句1 = 1,以防止这种情况的发生。但当数据量很大时,会 严重影响查询效率。
  • 通过使用<where>标签可以避免产生此类问题,<where>标签通常用来包含多个<if>标签,当多个<if>标签中有一个成立的, <where>会自动增加一个where关键字,并去掉<if>标签中sql语句多余的and ,or等。当没有<if>标签成立,则不会添加where子句。
<where>
	<if test=""></if>
    <if test=""></if>
</where>

dao接口声明的方法:
List<Student> selectStudentWhere(Student student);

sql映射文件
<select id="selectStudentWhere" resultType="com.sysu.entity.Student">
	select id,name,email,age from student
    <where>
    	<if test = "name != null and name != ''">
        	name = #{name}
        </if>
        <if test = "age > 0">
            or age > #{age}
        </if>
    </where>
</select>
    
测试方法:
@Test
public void testSelectWhere() throws IOException {
     SqlSession sqlSession = MyBatisUtils.getSqlSession();
     Student dao = sqlSession.getMapper(StudentDao.class);
         
     Student param = new Student();
     param.setName("abc");
     param.setAge(18);
     List<Student> studentList = studentDao.selectStudentWhere(param);
     for(Student stu:students) System.out.println(stu);
}
此代码段的含义为:在student表中查找所有名字为“abc”或者年龄大于18的数据。如果两个条件都不满足,则输出student表中的全部数据。

4.3 foreach标签

  • <foreach>标签用于实现对于数组与集合的遍历,一般用于dao接口文件中声明的方法的传入参数为数组或者集合。
  • 主要用在sql的in语句中。 select * from student where id in (1001,1002,1003)
使用语法:
<foreach collection="" item="" open="" close="" separator="">
	#{item的值}
</foreach>

collection:表示接口中的方法参数的类型,如果是数组使用array, 如果是list集合使用list,集合的大小用			list.size()表示。
item:自定义的,表示数组和集合成员的变量
open:循环开始的字符
close:循环结束的字符
separator:集合成员之间的分隔符
因为foreach一般用于sql中的in语句,所以open="("	close=")"	separator=","

遍历List<简单类型>

需求:输出学生id为1002,1005,1006的学生信息。

接口方法:
List<Student> selectStudentForList(List<Integer> idList);
    
sql映射文件
<select id = "selectStudentForList" resultType = "com.sysu.entity.Student">
	select id,name,email,age from student
    <if test="list != null and list.size() > 0">
    	where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
        	#{stu}
        </foreach>
    </if>
</select>    

测试方法:
@Test
public void testSelectForList() {
     SqlSession sqlSession = MyBatisUtils.getSqlSession();
     Student dao = sqlSession.getMapper(StudentDao.class);
    
     List<Integer> list = new ArrayList<>();
     list.add(1002);
     list.add(1005);
     list.add(1006);
     List<Student> studentList = studentDao.selectStudentForList(list);
     for(Student stu:students) System.out.println(stu);
}

遍历List<对象类型>

需求:输出学生id为1002,1005的学生信息。

接口方法:
List<Student> selectStudentForList(List<Student> idList);
    
sql映射文件
<select id = "selectStudentForList" resultType = "com.sysu.entity.Student">
	select id,name,email,age from student
    <if test="list != null and list.size() > 0">
    	where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
        	#{stu.id}
        </foreach>
    </if>
</select>    

测试方法:
@Test
public void testSelectForList() {
     SqlSession sqlSession = MyBatisUtils.getSqlSession();
     Student dao = sqlSession.getMapper(StudentDao.class);
    
     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.selectStudentForList(list);
     for(Student stu:students) System.out.println(stu);
}

4.4 sql标签

  • <sql>标签用于定义 SQL 片断,以便其它SQL标签可以复用定义好的片段。
  • 其它标签使用该 SQL 片断,需要使用<include>标签。
  • <sql>标签可以定义 SQL 语句中的任何部分,所以子标签可以放在动态 SQL 的任何位置。
先定义:<sql id="自定义名称唯一"> 可以是sql语句、表名、字段名等 </sql>
再使用:<include refid="id的值"/>

接口方法:
List<Student> selectStudentSqlFragment(List<Student> stuList);
    
sql映射文件:
<!--创建 sql 片段 id:片段的自定义名称-->
<sql id="studentSql">
	select id,name,email,age from student
</sql>
    
<select id="selectStudentSqlFragment" resultType="com.sysu.entity.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>
    
测试方法:
@Test
public void testSelectForList() {
     SqlSession sqlSession = MyBatisUtils.getSqlSession();
     Student dao = sqlSession.getMapper(StudentDao.class);
    
     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.selectStudentForList(list);
     for(Student stu:students) System.out.println(stu);
}
借助sql标签输出学生id为1002,1005的学生信息。

5.MyBatis配置文件(了解)

MyBatis有两种配置文件:主配置文件以及sql映射文件(mapper文件)

5.1 主配置文件

<!--
    MyBatis的主配置文件:主要定义数据库的配置信息以及sql映射文件的位置
    1.约束文件
        <!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
        mybatis-3-config.dtd约束文件的名称
    2.<configuration>根标签,该标签通常包括两部分:
        <environments>:数据库的连接信息
        <mappers>:sql映射文件的位置(相对于main/java而言)
-->

<?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>
<!--    environments是复数,表示可以管理多个数据库的连接信息,所以default的值必须与其中一个的<environment id="">相同-->
    <environments default="development">
        <environment id="development">
            
            <transactionManager type="JDBC"/>
<!--    transactionManager用于定义提交事务、回滚事务的方式。type有两种取值:
		(1)JDBC:表示mybatis底层调用JDBC中的Connection对象进行事务的处理
		(2)MANAGED:将mybatis的事务处理委托给其他容器(例如spring等)-->
            
            <dataSource type="POOLED">
<!--    type:指定数据连接的类型
		(1)POOLED:使用连接池
		(2)UNPOOLED:不使用连接池,每次执行sql语句都新建连接,执行完sql语句后在关闭连接。-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
                <!-- 通常情况下需要把数据库的连接信息放到一个单独的文件中,这个文件一般称为属性配置文件。-->  
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <!--加载sql映射文件,方式一(主流):-->  
        <mapper resource="com/sysu/dao/StudentDao.xml"/>
        <!--方式二(了解):可以加载com.sysu.dao包中的所有sql映射文件-->  
        <packge name="com.sysu.dao"/>
    </mappers>
</configuration>

主配置文件一般放在resourcs目录下,且命名为xxx.xml。主配置文件的具体内容可以见2.1

主配置文件特点:

  • 主配置文件中<configuration>之间的标签都是有序的,且<configuration>为根标签

    • <property>:指定属性配置文件的位置

    • <typeAliases>:配置别名

    • <plugins>:配置插件

    • <environments>:定义数据源

    • <mappers>:定义sql映射文件的位置

  • xml 文件,需要在头部使用约束文件

<?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"

属性配置文件的书写

数据库的属性配置文件: 把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。目的是便于修改,保存,处理多个数据库的信息。

(1) 在resources目录中定义一个属性配置文件,xxxx.properties,例如 jdbc.properties。在属性配置文件中进行数据的定义,格式是key = value。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql//.....
jdbc.username=root
jdbc.password=123456

(2) 在mybatis的主配置文件中,使用<property>指定属性配置文件的位置,然后在需要使用的地方利用${key}进行值的引入。

5.2 sql映射文件

详细内容见2.1即可。

posted @ 2021-06-09 22:01  控球强迫症  阅读(82)  评论(0编辑  收藏  举报