SSM---Mybatis

Mybatis基础教程

一、简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

需要使用到的jar包:

  • mysql-connector-java.jar
  • mybatis.jar

注:如果使用maven创建项目的化,可以取maven仓库找到对应的mybatis包,再导入xml就好。

1、持久化的简介

数据持久化:

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(Jdbc),io文件持久化。

持久层:

例如:DAO层、Service层、Controller层

  • 完成持久化工作的代码块
  • 底层界限十分明显

2、Mybatis的特点

  • 方便写入数据到数据库中。
  • 不需要再写传统的JDBC代码,简化了代码,自动化。
  • sql和代码分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射。
  • 提供对象关系映射标签,支持对象关系组建维护。
  • 提供xml标签,支持编写动态sql

二、创建一个简单的Mybaits程序

在此之前需要新建一个数据库数据;

CREATE DATABASE `mybatis`;

USE `mybatis`;

CREATE TABLE `user`(
  `id` INT(20) NOT NULL PRIMARY KEY,
  `name` VARCHAR(30) DEFAULT NULL,
  `pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;

--自行插入数据到数据表中;

接下来创建一个项目,导入所需要的所有Jar包,然后就可以编写代码了;

创建一个database.properties,用来定义JDBC数据连接数据库:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:/本机地址:3306/数据库?useUnicode=true&characterEncoding=utf-8&useSSL=true
username=数据库账号
password=密码

最重要的一点,编写mybaits-config.xml核心配置:

(可以查看Mybatis开发文档:https://mybatis.org/mybatis-3/zh/index.html)

<?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核心配置文件-->
<configuration>
    <!--  获取配置文件database.properties  -->
    <properties resource="database.properties"></properties>
    <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="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--  每一个Mapper.xml都需要在Mybatis核心配置中注册!  -->
    <mappers>
        <mapper resource="com/vxzx/dao/UserMapper.xml"></mapper>
    </mappers>
</configuration>

可以再编写一个获取Mybatis的Sqlsession的工具类:

package com.vxzx.utils;

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 MybatisUtils {
    //获取SqlSessionFactory对象:
    public static SqlSession getsqlSession(){
        SqlSession session = null;
        String resource = "mybaits-config.xml";
        try {
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            session = sessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return session;
    }
}
  • pojo层的User类:
package com.vxzx.pojo;

public class User {
    private Integer id;
    private String name;
    private String pwd;

    public User() {
    }

    public User(Integer id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", pwd='" + pwd + '\'' +
            '}';
    }
}
  • UserMapper接口:
package com.vxzx.dao;
import com.vxzx.pojo.User;
import java.util.List;
import java.util.Map;

public interface UserMapper {
    //获取所有用户信息:
    List<User> getUserList();
    //添加一个用户:
    int addUser(User user);
    //使用map修改用户:
    int updateUser2(Map<String,Object> map);
    //模糊查询:
    List<User> getUserByLike(String value);
}
  • UserMapper.xml (在这里面类似于编写以前的JDBC查询代码:)
<?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命名空间=绑定的一个对应的Mapper接口 -->
<mapper namespace="com.vxzx.dao.UserMapper">
    <!-- select:查询语句;  id:对应引用的方法名;resultType:返回结果集 -->
    <select id="getUserList" resultType="com.vxzx.pojo.User">
        select * from user
    </select>
    -- 只能修改pwd的数据,不能修改其他的数据:
    <insert id="addUser" parameterType="com.vxzx.pojo.User">
        insert into user(id,name,pwd) values(#{id},#{name},#{pwd})
    </insert>

    <update id="updateUser2" parameterType="map">
        update user set name=#{username},pwd=#{password} where id=#{id}
    </update>
    <select id="getUserByLike" resultType="com.vxzx.pojo.User">
        select * from user where name like #{value}
    </select>
</mapper>
  • UserMapperTest测试类:
//查询所有用户信息:
public void getUserList(){
    //1、获取SqlSession对象:
    SqlSession session = MybatisUtils.getsqlSession();
    //2、执行SQL: ----方式一:推荐使用
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> userList = mapper.getUserList();
    //2、执行SQL: ----方式二:
    //        List<User> userList = session.selectList("com.vxzx.dao.UserMapper.getUserList");
    for (User user : userList) {
        System.out.println(user);
    }
    session.close();
}
//添加用户:
public void addUser(){
    SqlSession session = MybatisUtils.getsqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    int user1 = mapper.addUser(new User(5, "vxzx", "123"));
    if (user1 > 0){
        System.out.println("添加成功!");
    }
    //提交事务:必须执行,不然添加不进去
    session.commit();
    session.close();
}
//使用map修改用户:
public void updateUser(){
    SqlSession session = MybatisUtils.getsqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    Map<String,Object> map = new HashMap<String, Object>();
    //格式:(sql语句中的#{}的值,新的值);可以插入一个或多个,不用全部插入
    map.put("username","vx");
    map.put("password","111111");
    map.put("id",4);
    mapper.updateUser2(map);
    session.commit();
    session.close();
}
//模糊查询:
public void getUserByLike(){
    SqlSession session = MybatisUtils.getsqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> userList = mapper.getUserByLike("%x%");
    for (User user : userList) {
        System.out.println(user);
    }
    session.close();
}

如果出现配置文件无法导出或者生效的问题,可以在项目对应的pom.xml插入以下配置代码:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

三、Mybatis的CRUD

接下来,我们可以对上面代码进行详细的解析:

1、namespace

namespace中的包名要和 Dao/mapper 接口的包名一致!

2、select

选择,查询语句;

  • id : 就是对应的namespace中的方法名;
  • resultType:Sql语句执行的返回值!
  • parameterType : 参数类型!

2.1 编写接口

//根据ID查询用户
User getUserById(int id);

2.2 编写对应的mapper的sql语句

<select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User">
    select * from mybatis.user where id = #{id}
</select>

2.3 测试

public void getUserById() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.getUserById(1);
    System.out.println(user);
    sqlSession.close();
}

3、Insert

3.1 编写对应的mapper的sql语句

<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="com.kuang.pojo.User">
    insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>

4、update

4.1 编写对应的mapper的sql语句

<update id="updateUser" parameterType="com.kuang.pojo.User">
    update mybatis.user set name=#{name},pwd=#{pwd}  where id = #{id} ;
</update>

5、delete

5.1 编写对应的mapper的sql语句

<delete id="deleteUser" parameterType="int">
    delete from mybatis.user where id = #{id};
</delete>

注意:增删改需要使用commit()提交事务;

6、使用map来定义数据中的数据

假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!

6.1 编写代码

  • 编写接口类:
//万能的Map
int updateUser(Map<String,Object> map);
  • 编写对应的mapper的sql语句
<update id="updateUser2" parameterType="map">
    update user set name=#{username},pwd=#{password} where id=#{id}
</update>
  • 编写测试类:
public void updateUser(){
SqlSession session = MybatisUtils.getsqlSession();
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<String, Object>();
    //格式:(sql语句中的#{}的值,新的值);可以插入一个或多个,不用全部插入
    map.put("username","vx");
    map.put("password","111111");
    map.put("id",4);
    mapper.updateUser2(map);
    session.commit();
    session.close();
    }

6.2 注意点

Map传递参数,直接在sql中取出key即可! 【parameterType="map"】

对象传递参数,直接在sql中取对象的属性即可!【parameterType="Object"】

只有一个基本类型参数的情况下,可以直接在sql中取到!

多个参数用Map,或者注解!

7、Mybatis的模糊查询

7.1 Java代码执行的时候,传递通配符 % %

对应的mapper的sql语句:

<select id="getUserByLike" resultType="com.vxzx.pojo.User">
    select * from user where name like #{value}
</select>

测试类中获取数据:

List<User> userList = mapper.getUserLike("%李%");	//加上通配符 % %

7.2 在sql拼接中使用通配符% %

一:对应的mapper的sql语句:

<select id="getUserByLike" resultType="com.vxzx.pojo.User">
    select * from user where name like "%"#{value}"%"
</select>

测试类中获取数据:

List<User> userList = mapper.getUserLike("李");		//在mapper中已加通配符,这里不用加了

四、Mybatis配置详解

核心配置文件:

  • configuration(配置)
  • properties(属性)
  • settings(设置)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境配置)
  • environment(环境变量)
  • transactionManager(事务管理器)一般都为JDBC
  • dataSource(数据源)一般都为POOLED,配置连接数据的数据源
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)

注意:各种配置必须严格按照其固定的顺序来使用。

1、 配置之属性

(1)属性(properties)

使用properties来引用外部数据源;例如:引入JBDC数据库连接;【database.properties】

这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。

database.properties:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true
username=root
password=123456

在核心配置中直接引入:

<properties resource="database.properties"/>

在核心配置中添加一些配置:

<properties resource="db.properties">
    <property name="username" value="root"/>
    <property name="pwd" value="11111"/>
</properties>

注意:如果两个文件有同一个字段,那么会优先使用外部的配置信息。

(2)环境配置(environments)

Mybatis可以配置多种环境来使用;但是每个SqlSessionFactory实例只能使用一种配置。

其中,Mybatis默认的transactionManager一般为JDBC,dataSource为POOLED连接池。

  • default:环境配置默认选择的配置;
  • id:每个配置的标志,用以来区分各个配置;
<environments default="environment">
    <environment id="environment">
        <transactionManager type="JDBC"></transactionManager>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

2、 配置之别名

(1)设置(settings)

MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

例如:配置日志文件实现;

<settings>
    <setting name="logImpl" value="log4j"/>
</settings>

(2)类型别名(typeAliases)

  • 别名的存在是为java类型设置一个简短的名字;
  • 可以减少类完全限定名的冗余;

使用设置别名,别名的使用:为该包下面的类首字母小写的类名字。

<typeAliases>
    <package name="com.vxzx.pojo"/>
</typeAliases>

使用设置别名,别名的使用:为alias后面的名字。

其中type为需要设置的类,alias为设置的别名。

<typeAlias type="com.vxzx.pojo.User" alias="user"></typeAlias>

后还想自己定义别名,可以使用注解来设置别名:

@Alias("user")
pubic class user(){}

3、 配置之映射器

  • MapperRegistry:注册绑定我们的Mapper文件
  • 配置对应的mapper映射文件 .xml
  • 每一个Mapper.XML都需要在Mybatis核心配置文件中注册

我们有三种方法可以使用:

一:常用(无其他注意点)

<mappers>
    <mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>

二:使用class文件绑定注册

<mappers>
    <mapper class="com.kuang.dao.UserMapper"/>
</mappers>

注意:

  • 接口与其对应的Mapper配置必须同名
  • 接口与其对应的Mapper配置必须在听一个包下面

三:使用扫描包的方式注册绑定

<mappers>
    <package name="com.kuang.dao"/>
</mappers>

注意:

  • 接口与其对应的Mapper配置必须同名
  • 接口与其对应的Mapper配置必须在听一个包下面

4、 生命周期与作用域

SSM---Mybatis

它的过程可以简单的理解为:创建sql工厂,打开sqlSession,使用Mapper来操作CRUD;

SqlSessionFactoryBuilder

  • 用来创建SqlSessionFactory,一旦创建完成,SqlSessionFactoryBuilder将被销毁。
  • 可以设置为局部变量,因为只需要使用一次。

SqlSessionFactory

  • 一旦创建,SqlSessionFactory 将会存在于您的应用程序整个运行生命周期中。
  • 因此 SqlSessionFactory 的最佳作用域是应用作用域。
  • 最简单的就是使用单例模式或者静态单例模式。

SqlSession

  • 连接到连接池的一个请求!
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
  • 每个SqlSession里面可以有多个mapper业务。
  • 用完之后需要赶紧关闭,否则资源被占用!

5、 属性名与字段名不一致

实体类的属性名:

private Integer id;
private String name;
private String password;

数据库的字段名:

 id int(3) ;
 name varchar(10) ;
 pwd varchar(20) ;

其中,password与pwd就有区别。这样查询数据会查询出null。

解决方法一:直接在查询语句中设置别名as

<select id="getUserList" resultMap="resultmap">
    select id,name,pwd as password from user
</select>

解决方法二:使用resultMap结果映射

  • id:查询语句使用的resultMap名字;
  • type:映射的结果集类;
  • property:类中的属性名;
  • column:数据库中的字段名;
<resultMap id="resultmap" type="user">
    <!-- property:属性名; column:数据库字段名; -->
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="password" column="pwd"/>
</resultMap>

<select id="getUserList" resultMap="resultmap">
    select * from user
</select>

对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。

你已经对它相当了解了,就不需要显式地用到他们。

6、实现分页

(1)使用limit分页

使用limit分页跟在sql里面的使用步骤一样,不同的是,需要在xml中填加该语句。

<!--  将查询出来的结果从1开始,每页展示三个  -->
<select id="getUserlistLmit"  resultType="user">
    select * from mybatis.user limit 0,3;	
</select>

(2)使用RowBounds分页

Mybatis提供了一个简单的逻辑分页使用类RowBounds。

首先,第一步先实例化一个RowBounds对象,里面输入的值为数据(起始值,显示页面值)

public RowBounds(int offset, int limit)

然后使用SQLsession中的selectList方法:

List<User> userList = sqlSession.selectList("com.vxzx.dao.UserMapper.getUserList", null, rs);
//传入的值:(需要查询的类的接口--及里面的方法,Object,RowBounds)
public void getUserListRow(){
    //实现从第一开始,每页显示2条数据的显示;
    RowBounds rs = new RowBounds(0,2);
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    //注意,要使用selectList的方法;
    List<User> userList = sqlSession.selectList("com.vxzx.dao.UserMapper.getUserList", null, rs);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

了解一些分页插件: PageHelper

五、日志

1、 日志工厂

数据库操作出现问题,就可以使用日志文件来进行排错。

Mybatis中日志的具体实现,可以在settings(设置)中设置。

在Mybatis核心配置文件中配置:

<settings>
    <setting name="logImpl" value="log4j"/>
</settings>

还可以自己设置日志数据输出格式和路径:(log4j.properties)

2、Log4j

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件;过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程;通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

具体使用步骤:

(1)导入log4j的jar包:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

(2)log4j.properties:

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/vx.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

(3)配置log4j的实现:

<settings>
    <setting name="logImpl" value=""/>
</settings>

实际使用操作:

  • 在要使用log4j的类中,导入包 org.apache.log4j.Logger;
  • 日志对象,参数为当前类的class
import org.apache.log4j.Logger;

static Logger logger = Logger.getLogger(UserMapperTest.class);
  • 日志级别:
logger.info("输出的logger--->info");
logger.debug("输出的logger--->debug");
logger.error("输出的logger--->error");

3、扩展:使用注解开发

sql数据库的CURD我们都可以使用注解来进行简单的操作;

  • 查询:
@Select("select * from user where id=#{uid}")
User getId(@Param("uid")int id);
  • 添加:
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
int insertUser(User user);
  • 修改
@Update("update user set name=#{name} where id=#{id}")
int updateUser(User user);
  • 删除
@Delete("delete from user where id=#{uid}")
int deleteUser(@Param("uid")int id);

值得注意的一点是,需要在核心配置文件中绑定接口!

<!-- 使用注解方法=====绑定接口: -->
<mappers>
    <mapper class="com.vxzx.dao.UserMapper"></mapper>
</mappers>

4、Lombok

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

使用步骤:

  • 导入jar包;也可以添加maven依赖:
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>
  • 然后,在我们需要使用的实体类上面,添加上@Data
//导入lombok的jar包,使用Lombok注解,完成getter、setter
@Data               //etter、setter
@AllArgsConstructor     //有参构造
@NoArgsConstructor      //无参构造
@EqualsAndHashCode		//hashcode比较
@ToString
public class User {
    private Integer id;
    private String name;
    private String password;

}

六、SQL多数据处理

1、多对一处理

例如:多个学生对应一个老师的例子。

  • 对于学生来说,多个学生关联一个老师;----对象association
  • 对于老师来说,一个老师有很多学生;----集合collection
多对一查询:使用<resultMap>中的association;
    具体实现一:根据结果集映射查询
               先使用sql连表查询语句===>映射为resultMap;
               再使用resultMap,配置查询的数据的别名的问题,其中需要使用association,
               再在association里面配置数据库列信息;
    具体实现二:嵌套查询:
               先使用sql语句查询第一个表中的数据===>映射为resultMap;
               再使用resultMap,配置查询的第一个表;其中需要使用到association,
               注意的是,association里面不必在写查询语句了,只需要在标签处配置
               需要查询的第二个表的信息;
               接着,再查询第二表的信息,要与上面的resultMap进行配对。

对于这种问题,我们有两种方法:

实体类:

public class Student {
    private Integer id;
    private String name;
    private Teacher teacher;
}

接口类:

public List<Student> getStudent();
public List<Student> getStudent2();

第一种:根据查询嵌套处理

<!-- 多对一   方式一:-->
<select id="getStudent" resultMap="st">
    select * from student
</select>
<!--  复杂的属性需要:association->对象; collection->集合      -->
<resultMap id="st" type="student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="teacher">
    select * from teacher where id=#{tid}
</select>

第二种:按结果查询嵌套

<select id="getStudent2" resultMap="st2">
    select student.id as sid,student.name as sname,teacher.name as tname
    from student,teacher
    where student.tid = teacher.id
</select>
<resultMap id="st2" type="student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

2、一对多处理

例如:一个老师对应多个学生;

  一对多查询:使用<resultMap>中的collection;
    具体实现一:根据结果集映射查询
                先使用sql连表查询语句===>映射为resultMapp;
                在使用resultMap,配置查询语句的数据的别名问题,其中需要使用到collection;
                再在collection中配置查询数据库列的信息;
                注意的是:
                    相较于association,还需要多配置实体类中对应的
                    ofType(集合中获取泛型信息);
    具体实现二:嵌套查询:
               先使用sql语句查询第一个表中的数据===>映射为resultMap;
               在使用resultMap,配置查询的第一个表;其中是要到的collection;
               注意的是,collection里面不必在写查询语句了,只需要在标签处配置;
               注意的是:
                        相较于association,还需要多配置实体类中对应的
                        javaType(指定属性的类型),ofType(集合中获取泛型信息);
               最后,再进行查询第二个表,要与上面的resultMap进行配对;

对于这种问题,我们有两种方法:

实体类:

public class Student {
    private Integer id;
    private String name;
    private  Integer tid;
}
public class Teacher {
    private Integer id;
    private String name;
    List<Student> students;
}

接口类:

List<Teacher> getTeacher(@Param("tid") int id);
List<Teacher> getTeacher2(@Param("tid") int id);

第一种:根据查询嵌套处理

<!--  collection 方式一:  -->
<select id="getTeacher" resultMap="ts">
    select * from teacher where id = #{tid}
</select>
<resultMap id="ts" type="teacher">
    <collection property="students" javaType="ArrayList"
                ofType="Student" column="id" select="getstudent">
    </collection>
</resultMap>
<select id="getstudent" resultType="student">
    select * from mybatis.student where tid = #{tid};
</select>

第二种:按结果查询嵌套

<!--  collection 方式二:  -->
<select id="getTeacher2" resultMap="ts2">
    select s.id as sid,s.name as sname,t.name as tname,t.id as tid
    from student as s,teacher as t
    where s.tid = t.id and t.id = #{tid};
</select>
<resultMap id="ts2" type="teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <!--  javaType="" 指定属性的类型!
      集合中获取泛型信息,需要使用ofType获取
      -->
    <collection property="students" ofType="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>
</resultMap>

3、总结

  • 关联-----association【多对一】
  • 集合-----collection【一对多】
  • javaType 与 ofType
    • javaType用来指定实体类中属性的类型
    • ofType用来指定映射到List或集合中的pojo的类型,泛型中的约束类型

七、动态SQL

动态 SQL 是 MyBatis 的强大特性之一。借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

简单来说,动态SQL就是指根据不同的条件生成不同的SQL语句。

  • if
  • choose(when,otherwise)
  • trim(where,set)
  • foreach

1、if

接口编写:

//动态sql:if
public List<Blog> getBlogm(Map<String,String> map);

mapper配置编写:

<!-- 动态 SQL·if: -->
<select id="getBlogm" resultType="blog" parameterType="map">
    select * from mybatis.blog
    <where>
        <if test="title != null">
            and title = "blog1"
        </if>
        <if test="author != null">
            and author = "zx"
        </if>
    </where>
</select>

测试编写:

    public void getBlogm(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String,String> map = new HashMap();
      	map.put("title","blog1");

        List<Blog> blogm = mapper.getBlogm(map);
        System.out.println(blogm);
        sqlSession.close();
    }

2、choose (when, otherwise)

  • 相当于SQL语句中的条件筛选语句

其中接口类,测试类的配置基本都是一样的。

<!-- choose (when, otherwise):   -->
<select id="getBlogmChoose" resultType="blog" parameterType="map">
    select * from mybatis.blog
    <where>
        <choose>
            <when test=" title != null">
                and title = "title1"
            </when>
            <otherwise>
                and id = 2
            </otherwise>
        </choose>
    </where>
</select>

3、trim (where, set)

  • 相当于SQL语句中的修改语句
<update id="updateTrim" parameterType="map">
    update mybatis.blog
    <set>
        title=#{title}
    </set>
    where id=#{id}
</update>

4、foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。

<!-- foreach:   -->
<select id="getBlogmFe" parameterType="map" resultType="blog">
    select * from mybatis.blog where id in

    <foreach collection="list" item="item" index="1" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

注意

  • collection:指你需要迭代的对象;

  • item:集合项,在下面需要使用;

  • index:索引值;

  • open:迭代值开始的符号;

  • separator:迭代值中间的分隔符;

  • close:迭代值结尾的符号;

5、SQL片段

有的时候,我们可能会将一些功能的部分抽取出来,方便复用!这时候,我们就需要用到SQL片段了。

在代码中使用<sql>标签抽取公共代码,然后使用<include>标签在需要的地方引用公共代码片段。

  • 使用SQL标签抽取公共的部分
<!--  SQL片段:  -->
<sql id="psql">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>
  • 在需要使用的地方使用Include标签引用即可
<select id="getBlogm" resultType="blog" parameterType="map">
    select * from mybatis.blog
    <where>

        <include refid="psql"></include>

    </where>
</select>

八、简述缓存

一级缓存:存在于每一个测试类中,即一脱离了这个测试类,缓存就会被自动删除。默认开启

二级缓存:存在于每一个对应的Mapper中,即脱离了这个Mapper,缓存就会删除。需要手动开启

其中,开启二级缓存:

1、开启全局缓存

<!--显示的开启全局缓存-->
<setting name="cacheEnabled" value="true"/>

2、在需要使用的二级缓存的Mapper中使用:

<!--在当前Mapper.xml中使用二级缓存-->
<cache/>

也可以自定义缓存参数:

<!--在当前Mapper.xml中使用二级缓存-->
<cache  eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>

注意:开启二级缓存的时候,我们需要将实体类序列换,不然会出错。

上一篇:基于java web(ssm)+Mysql+微信小程序的图书捐赠管理系统设计与实现毕业设计毕业论文


下一篇:Spring系列-3.2 ApplicationContextAwareProcessor