11-SSM_MyBatis(下)

目录

九,获取自增的id值

1,id为Integer类型

2,id为String类型

十,输入映射——传递多个参数

1,parameterType

2,通过参数下标索引传递参数

3,通过@Param注解传递多个参数(常用!)

4,通过map传递多个参数

5,通过pojo类传递多个参数

十一,#{}和${}的区别

1,#{}

2,${}

2.1 举例——使用#{}方法

2.2 举例——使用${}方法

十二,输出映射resultType

1,输出简单类型

2,输出pojo类型

3,输出map类型

十三,输出映射resultMap

十四,属性名称与列名不一致的解决方案

1,使用列别名和resultType

2,使用resultMap(常用!)

十五,Mybatis全局配置文件

1,配置的内容

2,属性properties

3,设置settings

4,类型别名typeAliases

4.1 Mybatis中已经支持的别名

4.2 自定义别名

5,映射器Mappers

5.1 使用相对于类路径的资源引用

5.2 使用映射器接口实现类的完全限定类名

5.3 将包内的映射器接口实现全部注册为映射器--推荐

6,dataSources标签

7,事务

7.1  默认需要手动提交事务的

7.2 自动提交事务

十六,Mybatis关系映射

1,对一映射

1.1 添加实体类

1.2 mapper接口

1.3 映射方式

2,对多映射

2.1 修改实体类Team.java

2.2 接口中添加方法

2.3 映射方式

十七,动态SQL

1,where标签在select中的使用

2,set标签在update中的使用

3,forEach标签

3.1 批量添加

3.2 批量删除

十八,分页插件的使用

十九,Mybatis缓存

1,缓存的作用

2,一级缓存:自动开启,SqlSession级别的缓存

2.1 一级缓存分析

2.2 清除缓存的方法

3,二级缓存:Mapper级别的缓存

3.1 二级缓存使用步骤

3.2 禁止二级缓存

3.3 缓存的属性配置

二十,Mybatis反向生成插件

1,使用方法


九,获取自增的id值

有时候新插入一条记录后,需要获取这条记录的id(id往往设置为自增),这时就需要对mapper.xml文件进行一些修改。

1,id为Integer类型

1,修改TeamMapper.xml文件中的add

select LAST_INSERT_ID()就是用来获取最后插入数据的id

    <!--添加一个球队
    parameterType="com.kkb.pojo.Team" 将对象作为参数,
    #{值} 值必须是实体类中的属性名称,其实就是占位符?
    -->
    <insert id="add" parameterType="com.xxy.pojo.Team" >
        <!--新增成功之后将自增的ID赋值给参数属性teamId
        keyProperty:表示新增的id值赋值到哪个属性值红
        order:AFTER/BEFORE两个取值,表示selectKey中的sql语句在insert语句之前还是之后执行
        resultType:表示返回值类型
        -->
        <selectKey keyProperty="teamId" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        INSERT INTO `team` (`teamName`, `location`, `createTime`)
        VALUES (#{teamName}, #{location}, #{createTime})
    </insert>

2,测试

    @Test
    public void testTeamMapper() {
        TeamMapper teamMapper = sqlSession.getMapper(TeamMapper.class);
        Team team = new Team();
        team.setTeamName("云堇");
        team.setLocation("璃月");
        team.setCreateTime(new Date());
        int num = teamMapper.add(team);
        sqlSession.commit();// 提交之后,就已经执行了mapper.xml中selectKey的语句,即将id赋值给当前的team对象
        System.out.println(num);
        System.out.println("新增记录id: " + team.getTeamId());
    }

2,id为String类型

1,设计主键为字符串的表

2,创建新的实体类、mapper接口

3,创建新的mapper.xml文件

插入数据之前先获取36位字符串作为id放入属性recordId中

<!--namespace="名称必须与映射的类的名字一致,是完全限定名"--> 
<mapper namespace="com.kkb.mapper.GameRecordMapper"> 
    <!--添加一条比赛记录 --> 
    <insert id="add" parameterType="com.kkb.pojo.GameRecord" > 
        <!--插入数据之前先获取36位字符串作为id放入属性recordId中 
            order="AFTER/BEFORE" 在insert执行之前还是之后 
            resultType="返回值的类型" 
        --> 
        <selectKey keyProperty="recordId" order="BEFORE" resultType="java.lang.String"> 
            select uuid() 
        </selectKey> 
        INSERT INTO `mybatis`.`gamerecord` (`recordId`, `homeTeamId`, `gameDate`, `score`, `visitingTeamId`) VALUES (#{recordId}, #{homeTeamId},default, #{score}, #{visitingTeamId}) 
    </insert> 
</mapper>

4,在mybatis.xml中添加新的mapper.xml配置文件路径

5,测试

十,输入映射——传递多个参数

1,parameterType

parameterType:接口中方法参数的类型,类型必须是完全限定名或别名(稍后讲别名)。该属性非必须,因为Mybatis框架能自行判断具体传入语句的参数,默认值为未设置(unset)。

当sql语句中需要多个参数时,就不能使用parameterType方法了。

2,通过参数下标索引传递参数

#{arg[0]}、#{arg[1]}......、

#{param[1]}、#{param[2]}、

1,首先在TeamMapper接口中添加方法声明

List<Team> queryByRange(int min, int max);

2,在TeamMapper.xml中添加节点

<mapper namespace="com.xxy.mapper.TeamMapper">

    <!--多个参数:标签中不需要parameterType属性
        方式1:通过下标索引的方式
        select * from team where teamId >=#{arg0} and teamId <=#{arg1}; 也可以,注意下表索引
        细节1:
            mybatis3.3版本之前:可以直接写#{0} #{1}
            从mybatis3.4开始:#{arg0} #{arg1}... 或者是 #{param1} #{param2}...
        细节2:
            sql语句中不能使用小于号,使用转义符号替换;大于号没有限制,也可以使用转义符号替换>
            &gt;    greater than
            &lt;    less than
    -->
    <select id="queryByRange" resultType="com.xxy.pojo.Team">
        select * from team where teamId &gt;=#{param1} and teamId &lt;=#{param2};
    </select>

3,编写测试方法

    @Test
    public void testTeamMapper() {
        TeamMapper teamMapper = sqlSession.getMapper(TeamMapper.class);
        List<Team> teams = teamMapper.queryByRange(1000, 1003);
        for (Team t : teams) System.out.println(t);
    }

3,通过@Param注解传递多个参数(常用!)

1,修改TeamMapper接口中的方法声明

List<Team> queryByRange(@Param("min") int min, @Param("max") int max);

2,修改TeamMapper.xml中节点参数

<mapper namespace="com.xxy.mapper.TeamMapper">
    <!--方式2:通过注解的方式: 
        #{}中的名称必须与接口的方法中的参数注解@Param()保持一致 
        select * from team where teamId >=#{param1} and teamId &lt;= #{param2}; 
        不推荐,但是语法也是正确的,但是不能使用arg0,arg1...... 
    -->
    <select id="queryByRange" resultType="com.xxy.pojo.Team">
        select * from team where teamId &gt;=#{min} and teamId &lt;=#{max};
    </select>

3,测试方法同上

4,通过map传递多个参数

1,修改TeamMapper接口中的方法声明

List<Team> queryByRange(Map<String, Integer> map);

2,修改TeamMapper.xml中节点参数

<mapper namespace="com.xxy.mapper.TeamMapper">
    <!--方式3:通过map来传递多个参数:映射文件中的参数占位符必须和map中的String类型的字段名称一样-->
    <select id="queryByRange" resultType="com.xxy.pojo.Team">
        select * from team where teamId &gt;=#{min} and teamId &lt;=#{max};
    </select>

3,修改测试方法

    @Test
    public void testTeamMapper() {
        TeamMapper teamMapper = sqlSession.getMapper(TeamMapper.class);
        Map<String, Integer> map = new HashMap<>();
        map.put("min", 1000);
        map.put("max", 1003);
        List<Team> teams = teamMapper.queryByRange(map);
        for (Team t : teams) System.out.println(t);
    }

5,通过pojo类传递多个参数

与map传递多个参数类似,要求映射文件中的参数占位符必须和pojo类中的属性完全一致。适用于多个参数类型不一致的场景。

1,实体类

public class QueryVO {
    private String name;
    private Integer min;
    private Integer max;
    private String location;
}

2,TeamMapper接口添加如下内容

List<Team> queryByCondition(QueryVO vo);

3,TeamMapper.xml配置文件中添加如下

    方式4:#{}中的名称必须pojo的参数的属性保持一致-->
    <select id="queryByCondition" resultType="com.xxy.pojo.Team">
        select * from team
        where teamId>=#{min} and teamId&lt;=#{max}
        and teamName like #{name} and location=#{location}
    </select>

4,测试方法

    @Test
    public void test04(){
        QueryVO vo=new QueryVO();
        vo.setLocation("洛杉矶");
        vo.setName("%球队%");
        vo.setMin(1001);
        vo.setMax(1111);
        List<Team> teams = teamMapper.queryByCondition(vo);
        teams.forEach(team -> System.out.println(team));
    }

十一,#{}和${}的区别

1,#{}

表示一个占位符,通知Mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替sql 语句的“?”。这个是Mybatis 中的首选做法,安全迅速。

<select id="queryById" parameterType="int" resultType="com.xxy.pojo.Team"> 
    select * from team where teamId=#{id} 
</select> 

<!--Mybatis执行的时候是: 
    String sql="select * from team where teamId=?"; 
    PreparedStatement ps = conn.prepareStatement(sql); 
    ps.setInt(1,1001); 

    where teamId=? 实际就是 where teamId=#{id} 
    ps.setInt(1,1001) 中的1001会替换#{id} 
-->

2,${}

表示字符串原样替换(SQL注入漏洞的通常做法),通知Mybatis 使用$包含的“字符串”替换所在位置。使用 Statement或者PreparedStatement 把 sql 语句和${}的内容连接起来。

一般用在替换表名,列名,不同列排序等操作。

例如:根据球队名称,球队位置查询球队列表

2.1 举例——使用#{}方法

1,TeamMapper接口添加如下内容:

List<Team> queryByName(String teamName); 
List<Team> queryByLocation(String location);

2,TeamMapper.xml配置文件中添加如下

<select id="queryByName" resultType="com.xxy.pojo.Team"> 
    select * from team where teamName=#{teamName} 
</select> 

<select id="queryByLocation" resultType="com.xxy.pojo.Team"> 
    select * from team where location=#{location} 
</select> 

3,测试方法

    @Test
    public void test05(){
        System.out.println("根据名称查询:");
        List<Team> teams = teamMapper.queryByName("胡桃");
        teams.forEach(team -> System.out.println(team));
        System.out.println("根据位置查询:");
        List<Team> teams2 = teamMapper.queryByLocation("璃月");
        teams2.forEach(team -> System.out.println(team));
    }

2.2 举例——使用${}方法

1,TeamMapper接口添加如下内容:

List<Team> queryByFiled(@Param("column") String column,@Param("columnValue") String columnValue);

2,TeamMapper.xml配置文件中添加如下:

<select id="queryByFiled" resultType="com.xxy.pojo.Team"> 
    select * from team where ${column}=#{columnValue} 
</select> 

3,测试方法

    @Test
    public void test06(){
        System.out.println("根据名称查询:");
        List<Team> teams = teamMapper.queryByFiled("teamName","钟离");
        teams.forEach(team -> System.out.println(team));
        System.out.println("根据位置查询:");
        List<Team> teams2 = teamMapper.queryByFiled("location","璃月");
        teams2.forEach(team -> System.out.println(team));
    }

十二,输出映射resultType

执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。如果返回的是集合,设置的是集合元素的类型,而不是集合本身。

resultType 和 resultMap,不能同时使用。

1,输出简单类型

2,输出pojo类型

3,输出map类型

当我们只需要查询表中几列数据的时候可以将sql的查询结果作为Map的key和value。一般使用的是Map<Object,Object>.

Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录会抛出TooManyResultsException异常。

如果有多行,使用List<Map<Object,Object>>.

十三,输出映射resultMap

resultType要求数据库中的列名和实体类中的保持一致

resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和 java 对象属性名不一样的情况。

1,在TeamMapper接口中添加方法

List<Team> queryAll2();

2,添加select节点,并定义 resultMap,指定列名和属性的对应关系

    <!--resultMap 和resultType不能同时出现
    resultMap:是引用的自己创建resultMap的id-->
    <select id="queryAll2" resultMap="baseResultMap">
        select * from team;
    </select>
    <!--创建resultMap:相当于自己编写表中的列与实体类中的属性的映射
        id:resultMap的名称,要求唯一
        type:期待要映射为java的类型
    -->
    <resultMap id="baseResultMap" type="com.xxy.pojo.Team">
        <!--一般主键列用id,其余列用result
            column:表示数据库表中的列名,不区分大小写
            property:表示实体类中的对应的属性名,区分大小写
            javaType:实体类中的对应的属性的类型,可以省略,mybatis会自己推断
            jdbcType="数据库中的类型column的类型" 一般省略
        -->
        <id column="teamId" property="teamId" javaType="java.lang.Integer" ></id>
        <result column="teamName" property="teamName" javaType="java.lang.String"></result>
        <result column="location" property="location" javaType="java.lang.String"></result>
        <result column="createTime" property="createTime" javaType="java.util.Date"></result>
    </resultMap>

3,测试

    @Test
    public void test10(){
        List<Team> teams = teamMapper.queryAll2();
        teams.forEach(team-> System.out.println(team));
    }

十四,属性名称与列名不一致的解决方案

1,使用列别名和resultType

<?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.xxy.mapper.UsersMapper">
    <!--方式1:resultType中的实体类的属性作为查询语句中的别名,让别名和属性保持一致-->
    <select id="queryById" resultType="com.xxy.pojo.Users">
        select user_id as userId,user_name as userName,user_age as userAge from users where user_id=#{id};
    </select>
</mapper>

2,使用resultMap(常用!)

    <!--方式2:通过resultMap自行映射-->
    <select id="queryById2" resultMap="baseMap">
        select * from users where user_id=#{id};
    </select>
    <resultMap id="baseMap" type="com.kkb.pojo.Users">
        <id column="user_id" property="userId"/>
        <result column="user_name" property="userName"/>
        <result column="user_age" property="userAge"/>
    </resultMap>

十五,Mybatis全局配置文件

案例中使用的 mybatis.xml就是Mybatis的全局配置文件。

全局配置文件需要在头部使用约束文件。

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

1,配置的内容

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

configuration(配置) 

    properties--属性:加载外部的配置文件,例如加载数据库的连接信息 
    Settings--全局配置参数:例如日志配置 
    typeAliases--类型别名 
    typeHandlers----类型处理器 
    objectFactory-----对象工厂 
    Plugins------插件:例如分页插件 
    Environments----环境集合属性对象 
        environment(环境变量) 
            transactionManager(事务管理器) 
            dataSource(数据源) 
    Mappers---映射器:注册映射文件用

2,属性properties

属性可以在外部进行配置,并可以进行动态替换。我们既可以在 properties 元素的子元素中设置(例如DataSource节点中的properties节点),也可以在 Java 属性文件中配置这些属性。

数据源中有连接数据库的四个参数数据,我们一般都是放在专门的属性文件中,mybatis的全局配置文件直接从属性文件中读取数据即可。

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

jdbc.driver=com.mysql.cj.jdbc.Driver 
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT 
jdbc.username=root 
jdbc.password=root 

2,mybatis的全局配置文件引入属性文件

<properties resource="jdbc.properties"/>

3,使用属性文件中的值

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

3,设置settings

MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为.例如我们配置的日志就是应用之一。其余内容参考https://mybatis.org/mybatis-3/zh/configuration.html#settings

<!--配置日志--> 
<settings> 
    <setting name="logImpl" value="LOG4J"/> 
</settings>

4,类型别名typeAliases

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

一般是给resultType、parameterType取别名,其他地方的全限定名仍需保持原样。

4.1 Mybatis中已经支持的别名

4.2 自定义别名

推荐写法:批量定义别名。扫描指定包下的所有类,同时别名定义为类名,别名的首字母大小写都可以

<!--自定义类型别名--> 
<typeAliases> 
    <!--对单个的实体类定义别名--> 
    <typeAlias type="com.xxy.pojo.Team" alias="Team"/> 
    <!--推荐写法:批量定义别名:扫描指定包下的所有类,同时别名定义为类名,别名的首字母大小写都可以--> 
    <package name="com.kkb.pojo"/> 
</typeAliases> 

5,映射器Mappers

5.1 使用相对于类路径的资源引用

<mapper resource=""/>

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

<mapper resource="com/kkb/mapper/TeamMapper.xml" /> 

5.2 使用映射器接口实现类的完全限定类名

<mapper class=""/> 

使用mapper接口的完全限定名。要求:接口和映射文件同包同名 

<mapper class="com.kkb.mapper.GameRecordMapper"/>

5.3 将包内的映射器接口实现全部注册为映射器--推荐

<package name=""/>

指定包下的所有Mapper接口。 注意:此种方法要求 Mapper接口名称和 mapper 映射文件名称相同,且在同一个目录中。

<package name="com.kkb.mapper"/>

6,dataSources标签

Mybatis 中访问数据库支持连接池技术,而且是采用的自己的连接池技术。

在 Mybatis 的 mybatis.xml配置文件中,通过来实现 Mybatis 中连接池的配置。MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource。

Mybatis 的数据源分为三类:

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

前两个数据源都实现javax.sql.DataSource接口

7,事务

7.1  默认需要手动提交事务的

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

<transactionManager type="JDBC"/>

该标签用于指定 MyBatis所使用的事务管理器。MyBatis 支持两种事务管理器类型:JDBC 与 MANAGED。

  • JDBC:使用JDBC的事务管理机制,通过Connection对象的 commit()方法提交,通过rollback()方法 回滚。默认情况下,mybatis将自动提交功能关闭了,改为了手动提交,观察日志可以看出,所以我们在程序中都需要自己提交事务或者回滚事务。
  • MANAGED:由容器来管理事务的整个生命周期(如Spring容器)。

7.2 自动提交事务

SqlSessionFactory的openSession重载方法,可以设置自动提交的方式。 

如果sqlSession = SqlSessionFactory.openSession(true);参数设置为true,再次执行增删改的时候就不需要执行session.commit()方法,事务会自动提交。

十六,Mybatis关系映射

1,对一映射

球员对应一个球队(属性中添加球队实体)

1.1 添加实体类

public class Player {
    private Integer playerId;
    private String playerName;
    private Integer playerNum;
    private Integer teamId;
    //关系字段:多个球员可以属于同一个球队
    //多方(球员)持有一方(球队)的对象
    private Team team1;
    private Team team2;
    private Team team3;
    // 省略getter和setter方法
}

1.2 mapper接口

public interface PlayerMapper {
    Player queryById(int playerId);
    Player queryById1(int playerId);
    Player queryById2(int playerId);
    Player queryById3(int playerId);
}

1.3 映射方式

方式1:通过关联对象打点调用属性的方式

    <select id="queryById1" resultMap="joinTeamResult1">
        SELECT * FROM `player` p INNER JOIN team t
        on t.teamId=p.teamId
        where playerid=#{id}
    </select>
    <resultMap id="joinTeamResult1" type="Player" extends="baseResultMap">
        <!-- 这里的team1指Player类中的属性 -->
        <result column="teamId" property="team1.teamId"></result>
        <result column="teamName" property="team1.teamName"></result>
        <result column="location" property="team1.location"></result>
        <result column="createTime" property="team1.createTime"></result>
    </resultMap>

要求:

  • 两表的连接查询

方式2:直接引用关联对象的Mapper映射

    <select id="queryById2" resultMap="joinTeamResult2">
        SELECT * FROM `player` p INNER JOIN team t
        on t.teamId=p.teamId
        where playerid=#{id}
    </select>
    <resultMap id="joinTeamResult2" type="Player" extends="baseResultMap">
        <!-- 之前编写过TeamMapper.xml,这里直接引用那里的baseResultMap映射 -->
        <association property="team2" javaType="Team"
                     resultMap="com.kkb.mapper.TeamMapper.baseResultMap"/>
    </resultMap>

要求:

  • 1、两表的连接查询
  • 2、关联对象中已经存在被引用的resultMap

方式3:直接引用关联对象的单独查询的方法

    <select id="queryById3" resultMap="joinTeamResult3">
        <!-- 这里不再需要连接查询 -->
        select * from player where playerId=#{id}
    </select>
    <resultMap id="joinTeamResult3" type="Player" extends="baseResultMap">
        <!-- 引用了TeamMapper.xml中的查询节点select,相当于执行第二次sql查询 -->
        <association property="team3" javaType="Team"
                    select="com.kkb.mapper.TeamMapper.queryById" column="teamId"/>
    </resultMap>

要求:

  • 1、不需要两表的连接查询
  • 2、关联对象中已经存在被引用的查询方法

完整的PlayerMapper.xml文件 

<?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.kkb.mapper.PlayerMapper">


    <select id="queryByTeamId" resultMap="baseResultMap">
        select * from player where teamId=#{id}
    </select>
    <select id="queryById" resultMap="baseResultMap">
        select * from player where playerId=#{id}
    </select>
    <resultMap id="baseResultMap" type="Player">
        <id column="playerId" property="playerId"/>
        <result column="playerName" property="playerName"/>
        <result column="playerNum" property="playerNum"/>
        <result column="teamId" property="teamId"/>
    </resultMap>

    <!--方式1: 通过对象打点属性直接映射列名
        要求:必须连接查询
             一般会自定义结果映射-->
    <select id="queryById1" resultMap="joinTeamResult1">
        SELECT * FROM `player` p INNER JOIN team t
        on t.teamId=p.teamId
         where playerid=#{id}
    </select>
    <resultMap id="joinTeamResult1" type="Player" extends="baseResultMap">
        <!-- 这里的team1指Player类中的属性 -->
        <result column="teamId" property="team1.teamId"></result>
        <result column="teamName" property="team1.teamName"></result>
        <result column="location" property="team1.location"></result>
        <result column="createTime" property="team1.createTime"></result>
    </resultMap>

    <!--方式2:直接引用关联对象的Mapper映射
    要求:必须连接查询-->
    <select id="queryById2" resultMap="joinTeamResult2">
        SELECT * FROM `player` p INNER JOIN team t
        on t.teamId=p.teamId
         where playerid=#{id}
    </select>
    <resultMap id="joinTeamResult2" type="Player" extends="baseResultMap">
        <!-- 之前编写过TeamMapper.xml,这里直接引用那里的baseResultMap映射 -->
        <association property="team2" javaType="Team"
                     resultMap="com.kkb.mapper.TeamMapper.baseResultMap"/>
    </resultMap>
    <!--方式3:使用关联对象的单独的查询语句
    要求:不需要连接查询
        需要关联对象中存在对应的查询语句-->
    <select id="queryById3" resultMap="joinTeamResult3">
        select * from player where playerId=#{id}
    </select>
    <resultMap id="joinTeamResult3" type="Player" extends="baseResultMap">
        <!-- 引用了TeamMapper.xml中的查询节点select,相当于执行第二次sql查询 -->
        <association property="team3" javaType="Team"
                    select="com.kkb.mapper.TeamMapper.queryById" column="teamId"/>
    </resultMap>

    </mapper>

2,对多映射

一个球队含有多名球员(属性中添加球员列表)

2.1 修改实体类Team.java

public class Team implements Serializable {
    private Integer teamId;
    private String teamName;
    private String location;
    private Date createTime;
    //关系字段:一个球队可以拥有多个球员
    //一方(球队)持有多方(球员)的集合
    private List<Player> playerList1;
    private List<Player> playerList2;
}

2.2 接口中添加方法

TeamMapper.java

public interface TeamMapper { 
    Team queryById1(int teamId); 
    Team queryById2(int teamId);

PlayerMapper.java(为映射方式二做准备)

public interface PlayerMapper { 
    List<Player> queryByTeamId(int teamId);

2.3 映射方式

方式一:连接查询+引用关联对象的结果映射

    <select id="queryById1" resultMap="joinPlayMap1">
        select * from team t inner join player p
        on t.teamId=p.teamId where t.teamId=#{id}
    </select>
    <!--collection:多对映射的节点
    property:实体类中要查询的集合属性
    javaType:集合类型
    ofType:集合类型中元素的类型
    resultMap-->
    <resultMap id="joinPlayMap1" type="Team" extends="baseResultMap">
        <collection property="playerList1" javaType="arraylist" ofType="Player"
        resultMap="com.kkb.mapper.PlayerMapper.baseResultMap"/>
    </resultMap>

方式二:引用关联对象的单独查询的方法

    <select id="queryById2" resultMap="joinPlayMap2">
        select * from team where teamId=#{id}
    </select>
    <resultMap id="joinPlayMap2" type="Team" extends="baseResultMap">
        <collection property="playerList2" javaType="arraylist" ofType="Player"
        select="com.kkb.mapper.PlayerMapper.queryByTeamId" column="teamId"/>
    </resultMap>

十七,动态SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。

利用动态 SQL,可以彻底摆脱这种痛苦。使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

1,where标签在select中的使用

案例:球队的多条件查询

1,原先的多条件查询做法

/* 原有的多条件分析:都是通过java中的字符串拼接实现 
String sql="select * from team where 1 = 1 "; 

// 如果用户输入了名称,就模糊查询 
and teamName like '%?%' 

// 如果用户输入了日期,按照日期区间查询 
and createTime> ? and createTime< ? 

//如果输入了地区,按照地区查询 
and location =?";*/ 

if(vo.getName()!=null && !"".equals(vo.getName().trim())){ 
    sql+=" and teamName like '%"+vo.getName().trim()+"%'"; 
}

if(vo.getBeginTime()!=null ){ 
    sql+=" and getEndTime>"+vo.getBeginTime(); 
}

if(vo.getBeginTime()!=null ){ 
    sql+=" and createTime<="+vo.getEndTime(); 
}

if(vo.getLocation()!=null && !"".equals(vo.getLocation().trim())){ 
    sql+=" and location ="+vo.getLocation().trim(); 
} 

2,自己封装的查询条件类QueryTeamVO.java

public class QueryTeamVO {
    private String name;
    private Date beginTime ;
    private Date endTime;
    private String location;
}

3,TeamMapper.java接口添加

List<Team> queryByVO(QueryTeamVO vo);

4,TeamMapper.xml映射文件添加

为避免SQL注入问题,尽可能不使用字符串替换功能${},而是采用concat方法拼接字符串

    <!--多条件查询:
        模糊查询的写法可以使用3种方式:
        方式1: and teamName like #{name} ,传递参数的时候带上%,例如vo.setName("%人%")
        方式2: and teamName like ‘%${name}%’ 传递参数的时候没有%,例如vo.setName("人")
        方式3:  and teamName like concat(concat('%',#{name}),'%')  例如vo.setName("人")
            concat(str1,str2)函数是字符串拼接使用-->
    <select id="queryByVO" parameterType="QueryVO" resultMap="baseResultMap" useCache="false">
        select * from team
        <where>
            <!-- 如果用户输入了名称,就模糊查询   and teamName like '%?%'-->
            <if test="name!=null ">
                and teamName like concat(concat('%',#{name}),'%')
            </if>
            <if test="beginTime!=null ">
                and createTime>=#{beginTime}
            </if>
            <if test="endTime!=null ">
                and createTime&lt;=#{endTime}
            </if>
            <if test="location!=null ">
                and location=#{location}
            </if>
        </where>
    </select>

5,测试方法

    @Test
    public void test1(){
        QueryTeamVO vo=new QueryTeamVO();
        vo.setName("人");
        vo.setEndTime(new Date());
        vo.setLocation("加利福尼亚州洛杉矶");
        List<Team> teams = teamMapper.queryByVO(vo);
        for (Team team : teams) {
            System.out.println(team);
        }
    }

2,set标签在update中的使用

直接用对象更新数据库中的记录时,未设定值的属性可能会将数据库表中原有的字段覆盖掉。因此通常的做法是先查询记录,保存到对象中,再更改对象中的部分属性,最后执行更新语句。

1,原先的更新方法

<update id="update" parameterType="com.kkb.pojo.Team"> 
    update team set teamName=#{teamName},location=#{location},createTime=#{createTime} 
    where teamId=#{teamId} 
</update>

2,使用set标签构建动态的SQL语句

    <update id="update1" parameterType="com.kkb.pojo.Team">
        update team
        <set>
            <if test="teamName!=null">
                teamName=#{teamName},
            </if>
            <if test="location!=null">
                location=#{location},
            </if>
            <if test="createTime!=null">
                createTime=#{createTime},
            </if>
        </set>
        where teamId=#{teamId}
    </update>

3,forEach标签

3.1 批量添加

    <!--批量添加-->
    <insert id="addList" parameterType="arraylist">
        INSERT INTO team (teamName,location) VALUES
        <!--collection:要遍历的集合;参数是集合类型,直接写list
        item:遍历的集合中的每一个数据
        separator:将遍历的结果用,分割-->
        <foreach collection="list" item="t" separator=",">
            (#{t.teamName},#{t.location})
        </foreach>
    </insert>
    @Test
    public void test3(){
        List<Team> list=new ArrayList<>();
        for(int i=1;i<=3;i++){
            Team team=new Team();
            team.setTeamName("lina"+i);
            team.setLocation("bj"+i);
            list.add(team);
        }
        teamMapper.addList(list);
        MybatisUtil.getSqlSession().commit();
    }

3.2 批量删除

    <delete id="delList" >
        delete from team where teamId  in
        <!--collection:要遍历的集合;参数是集合类型,直接写list
        item:遍历的集合中的每一个数据
        separator:将遍历的结果用,分割
        open="(" close=")":表示将遍历结果用open close包裹起来-->
        <foreach collection="list" item="teamId" separator="," open="(" close=")">
            #{teamId}
        </foreach>
    </delete>
    @Test
    public void test4() {
        List<Integer> list = new ArrayList<>();
        list.add(1109);
        list.add(1110);
        list.add(1111);
        teamMapper.delList(list);
        MybatisUtil.getSqlSession().commit();
    }

十八,分页插件的使用

1,在pom.xml中引入jar依赖

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

2,在mybatis全局配置文件中添加插件配置

注意plugins节点位置(environments之前)

    <!--配置分页插件-->
    <plugins>
        <!--5.0版本之前使用的PageHelper,5.0之后使用PageInterceptor-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!--<property name="reasonable" value="true"/>-->
        </plugin>
    </plugins>

3,使用插件

    @Test
    public void test5() {
        // PageHelper.startPage 必须紧邻查询语句,而且只对第一条查询语句生效(拦截器,拦截查询语句)
        PageHelper.startPage(2,5);
        List<Team> teams = teamMapper.queryAll();//查询语句结尾不能有分号
        teams.forEach(team-> System.out.println(team));
        PageInfo<Team> info=new PageInfo<>(teams);
        System.out.println("分页信息如下:");
        System.out.println("当前页:"+info.getPageNum());
        System.out.println("总页数:"+info.getPages());
        System.out.println("前一页:"+info.getPrePage());
        System.out.println("后一页:"+info.getNextPage());
        System.out.println("navigatepageNums:"+info.getNavigatepageNums());
        for (int num : info.getNavigatepageNums()) {
            System.out.println(num);
        }
    }

4,部分源码

package com.github.pagehelper; 
import java.util.Collection; 
import java.util.List; 

/**
* 对Page<E>结果进行包装 
* <p/> 
* 新增分页的多项属性,主要参考:http://bbs.csdn.net/topics/360010907 
*
* @author liuzh/abel533/isea533 
* @version 3.3.0 
* @since 3.2.2 
* 项目地址 : http://git.oschina.net/free/Mybatis_PageHelper 
*/ 

@SuppressWarnings({"rawtypes", "unchecked"}) 
public class PageInfo<T> extends PageSerializable<T> { 

//当前页 
private int pageNum; 

//每页的数量 
private int pageSize; 

//当前页的数量 
private int size; 

//由于startRow和endRow不常用,这里说个具体的用法 
//可以在页面中"显示startRow到endRow 共size条数据" 
//当前页面第一个元素在数据库中的行号 
private int startRow; 

//当前页面最后一个元素在数据库中的行号 
private int endRow; 

//总页数 
private int pages; 

//前一页 
private int prePage; 

//下一页 
private int nextPage; 

//是否为第一页 
private boolean isFirstPage = false; 

//是否为最后一页 
private boolean isLastPage = false; 

//是否有前一页 
private boolean hasPreviousPage = false; 

//是否有下一页 
private boolean hasNextPage = false; 

//导航页码数 
private int navigatePages; 

//所有导航页号 
private int[] navigatepageNums; 

//导航条上的第一页 
private int navigateFirstPage; 

//导航条上的最后一页 
private int navigateLastPage;

十九,Mybatis缓存

1,缓存的作用

缓存是一般的ORM 框架都会提供的功能,目的就是提升查询的效率和减少数据库的压力。将经常查询的数据存在缓存(内存)中,用户查询该数据的时候不需要从磁盘(关系型数据库文件)上查询,而是直接从缓存中查询,提高查询效率,解决高并发问题。

MyBatis 也有一级缓存和二级缓存,并且预留了集成第三方缓存的接口。

Mybatis的缓存结构体系:

2,一级缓存:自动开启,SqlSession级别的缓存

在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据,将不再从数据库查询,从而提高查询效率。

当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。

Mybatis默认开启一级缓存,存在内存中(本地缓存)不能被关闭,可以调用clearCache()来清空本地缓存,或者改变缓存的作用域。

2.1 一级缓存分析

当用户发起第一次查询team=1001的时候,先去缓存中查找是否有team=1001的对象;如果没有,继续向数据中发送查询语句,查询成功之后会将teamId=1001的结果存入缓存
中;

当用户发起第2次查询team=1001的时候,先去缓存中查找是否有team=1001的对象,因为第一次查询成功之后已经存储到缓存中,此时可以直接从缓存中获取到该数据,意味
着不需要再去向数据库发送查询语句。

如果SqlSession执行了commit(有增删改的操作),此时该SqlSession对应的缓存区域被整个清空,目的避免脏读。

前提:SqlSession未关闭。

测试:

    //测试一级缓存:自动开启,sqlSession级别的缓存
    @Test
    public void test1() {
        Team t1=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//第一次查询,先查缓存,此时缓存中没有,继续向数据库发送查询语句
        System.out.println(t1);//查询完毕之后数据被自动存入缓存区域
        Team t2=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//第二次查询,因为缓存中已经有了该数据,可以直接获取,不需要发送查询语句
        System.out.println(t2);
        MybatisUtil.closeSqlSession();//关闭连接,缓存清空
        sqlSession=MybatisUtil.getSqlSession();//再次获取连接,此时缓存为空
        Team t3=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//新连接下第一次查询,肯定发送查询语句
        System.out.println(t3);//查询完毕之后数据被自动存入缓存区域
        int num=sqlSession.delete("com.kkb.mapper.TeamMapper.del",10000);
        sqlSession.commit();//提交之后缓存被整个清空
        System.out.println("删除结果:"+num);
        Team t4=sqlSession.selectOne("com.kkb.mapper.TeamMapper.queryById",1001);//第二次查询,因为缓存已经被上一次的提交清空了,所以还是需要发送查询语句
        System.out.println(t4);
        sqlSession.close();
    }

没有重复发送sql语句,说明缓存有存储;

只要提交删除语句,即使没有符合条件的记录,缓存仍然会清空;

2.2 清除缓存的方法

  • 1、 session.clearCache( ) ;
  • 2、 execute update(增删改) ;
  • 3、 session.close( );
  • 4、 xml配置 flushCache="true" ; 
  • 5、 rollback; 
  • 6、 commit。

3,二级缓存:Mapper级别的缓存

多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace。

不同的sqlSession两次执行相同namespace下的sql语句参数相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据,将不再从数据库查询,从而提高查询效率。

Mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。

如果缓存中有数据就不用从数据库中获取,大大提高系统性能。

二级缓存原理图:

3.1 二级缓存使用步骤

二级缓存是mapper范围级别的,默认不启用。

1,在Mybatis框架的全局配置文件中开启二级缓存

2,在需要二级缓存的Mapper中添加缓存标志

3,实体类必须实现Serializable接口

 4,测试

如果两个session不是从同一个Factory获取,那么二级缓存将不起作用。

    @Test
    public void test2() {
        SqlSession sqlSession1 = MybatisUtil.getSqlSession();
        Team t1 = sqlSession1.selectOne("com.kkb.mapper.TeamMapper.queryById", 1001);//先查缓存,没有,先数据库,查询完毕写入二级缓存
        System.out.println(t1);
        MybatisUtil.closeSqlSession();//关闭连接,一级缓存清空,二级缓存存在

        SqlSession sqlSession2 = MybatisUtil.getSqlSession();
        Team t2 = sqlSession2.selectOne("com.kkb.mapper.TeamMapper.queryById", 1001);//先查缓存,有,直接获取,不需要查询数据库
        System.out.println(t2);
        MybatisUtil.closeSqlSession();//关闭连接,一级缓存清空,二级缓存存在

        SqlSession sqlSession3 = MybatisUtil.getSqlSession();
        int num = sqlSession3.delete("com.kkb.mapper.TeamMapper.del", 10000);//删除成功
        System.out.println("删除的结果:" + num);
        sqlSession3.commit();//提交之后清空二级缓存
        MybatisUtil.closeSqlSession();//关闭连接,缓存清空

        SqlSession sqlSession4 = MybatisUtil.getSqlSession();
        Team t3 = sqlSession4.selectOne("com.kkb.mapper.TeamMapper.queryById", 1001);先查缓存,曾经有,但是上一个提交已经清空了缓存,所以只能去数据库中查询,查询完毕写入二级缓存
        System.out.println(t3);
        MybatisUtil.closeSqlSession();//关闭连接,缓存清空
    }

3.2 禁止二级缓存

对于变化比较频繁的SQL,可以禁用二级缓存。

在开始了二级缓存的XML中对应的statement中设置useCache=false禁用当前Select语句的二级缓存。

useCache默认值是true。对于一些很重要的数据尽量不放在二级缓存中。

3.3 缓存的属性配置

    <cache>
        <property name="eviction" value="LRU"/><!--回收策略为LRU-->
        <property name="flushInterval" value="60000"/><!--自动刷新时间间隔为60S-->
        <property name="size" value="1024"/><!--最多缓存1024个引用对象-->
        <property name="readOnly" value="true"/><!--只读-->
    </cache>

部分源码

@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
public @interface CacheNamespace { 
    Class<? extends Cache> implementation() default PerpetualCache.class; 
    Class<? extends Cache> eviction() default LruCache.class; 
    long flushInterval() default 0; 
    int size() default 1024; 
    boolean readWrite() default true; 
    boolean blocking() default false; 
    Property[] properties() default {}; 
}

/**属性介绍: 
1.映射语句文件中的所有select语句将会被缓存; 

2.映射语句文件中的所有CUD操作将会刷新缓存; 

3.缓存会默认使用LRU(Least Recently Used)算法来收回; 
3.1、LRU – 最近最少使用的:移除最长时间不被使用的对象。 
3.2、FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 
3.3、SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 
3.4、WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。 

4.缓存会根据指定的时间间隔来刷新(默认情况下没有刷新间隔,缓存仅仅调用语句时刷新);
 
5.缓存会存储列表集合或对象(无论查询方法返回什么),默认存储1024个对象。 

6.缓存会被视为是read/write(可读/可写)的缓存,意味着检索对象不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
**/

如果想在命名空间中共享相同的缓存配置和实例(使用其他mapper.xml文件中缓存配置),可以使用cache-ref 元素来引用另外一个缓存。 

// 引用TeamMapper命名空间中的cache。
<cache-ref namespace="com.kkb.mapper.TeamMapper" />

二十,Mybatis反向生成插件

反向生成即,自动生成实体类、mapper接口、映射文件

1,使用方法

1,在pom.xml文件中的中中添加如下插件配置

            <!--反向生成插件-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.5</version>
                <configuration>
                    <!--配置文件的路径-->
                    <!-- 需要在对应位置手动创建generatorConfig.xml -->
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.5</version>
                    </dependency>
                </dependencies>
            </plugin>

2,generatorConfig.xml内容

标号的位置需要根据自己的实际项目更改。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<!-- 配置生成器:标了序号的部分都需要修改为自己的内容 -->
<generatorConfiguration>
    <!--1、数据库驱动jar:添加自己的jar路径 -->
    <classPathEntry
            location="D:\repository\mysql\mysql-connector-java\8.0.23\mysql-connector-java-8.0.23.jar" />

    <context id="MyBatis" targetRuntime="MyBatis3">

        <!--去除注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--2、数据库连接 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT"
                        userId="root"
                        password="root">
        </jdbcConnection>

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer;
        为 true时把JDBC DECIMAL和NUMERIC类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--3、生成实体类 指定包名 以及生成的地址 (可以自定义地址,但是路径不存在不会自动创建
        使用Maven生成在target目录下,会自动创建) -->
        <javaModelGenerator targetPackage="org.xzk.pojo"
                            targetProject="src\main\java">
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!--4、生成SQLmapper.xml映射文件 -->
        <sqlMapGenerator targetPackage="org.xzk.mapper"
                         targetProject="src\main\resources">
        </sqlMapGenerator>
        <!--5、生成Dao(Mapper)接口文件,-->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="org.xzk.mapper"
                             targetProject="src\main\java">
        </javaClientGenerator>

        <!--6、要生成哪些表(更改tableName和domainObjectName就可以) -->
        <!-- tableName:要生成的表名
        enableCountByExample:Count语句中加入where条件查询,默认为true开启
        enableUpdateByExample:Update语句中加入where条件查询,默认为true开启
        enableDeleteByExample:Delete语句中加入where条件查询,默认为true开启
        enableSelectByExample:Select多条语句中加入where条件查询,默认为true开启
        selectByExampleQueryId:Select单个对象语句中加入where条件查询,默认为true开启
        -->
        <!-- 这里表示严格按照数据库表中的命名方式,由于数据库中大小写不敏感,所以为了符合Java的命名规范,建议添加 -->
        <!-- 如果数据库中表的命名用下划线分隔,这里就不需要添加,会自动生成符合Java规范的名称 -->
        <table tableName="Team">
            <property name="useActualColumnNames" value="true"/>
        </table>
        <table tableName="Player">
            <property name="useActualColumnNames" value="true"/>
        </table>
        <table tableName="gameRecord">
            <property name="useActualColumnNames" value="true"/>
        </table>
        <!-- 这里如果不设置为false,默认自动生成数据库表的基础操作,比如查询所有、条件查询等 -->
        <!--<table tableName="Team"
               enableCountByExample="false"
               enableUpdateByExample="false"
               enableUpdateByPrimaryKey="false"
               enableDeleteByExample="false"
               enableDeleteByPrimaryKey="false"
               enableSelectByExample="false"
               selectByExampleQueryId="false">
            <property name="useActualColumnNames" value="true"/>
        </table>-->
    </context>
</generatorConfiguration>

3,运行插件

注意只能运行一次(),运行完毕显示BUILD SUCCESS即为成功。若想重新生成,需要将已生成的内容删除

 4,反向生成内容的使用

  • 使用之前需要在mybatis.xml配置文件中注册;
  • 增删改仍需要手动提交事务;
public class TestGenerator {
    private TeamMapper mapper= MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
    @Test
    public void test1(){
        Team team = mapper.selectByPrimaryKey(1001);
        System.out.println(team);
    }
    @Test
    public void test2(){
        Team team=new Team();
        team.setTeamName("lina-test");
        team.setLocation("bj");
        int i = mapper.insert(team);
        MybatisUtil.getSqlSession().commit();
        System.out.println(i);
    }
    @Test
    public void test3(){
        //可以理解为为多条件、排序等服务的类
        TeamExample example=new TeamExample();
        //理解为盛放条件的容器
        TeamExample.Criteria criteria = example.createCriteria();
        //向容器中添加条件
        criteria.andTeamNameLike("人");
        criteria.andTeamIdBetween(1001,1100);
        //排序
        example.setOrderByClause("teamName desc");
        List<Team> teams = mapper.selectByExample(example);
        for (Team team : teams) {
            System.out.println(team);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值