MyBatis3.4全集笔记

MyBatis

1. MyBatis 简介

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

iBATIS一词来源于"internet"和"abatis"的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)

MyBatis虽然改变了名字,但是实际的内核还是ibatis

MyBatis以高轻量级闻名于全球,提出以注入SQL的方式来管理持久化,让整个项目在数据库操作这块与SQL语言完全解耦,所以深受开发人员的喜爱

mybatis是一款高轻量级的基于ORM(对象关系映射)半自动化的持久层框架,它更加关注原生sql的编写,在实际开发过程中能够实现sql语句与业务代码的完全的解耦。它还支持强大的sql查询、存储过程、高级映射、缓存机制。还支持强大的基于OGNL动态sql的编写。

2. Maven MyBatis搭建

基础脚手架效果如图:

需要配置的几项内容:

(1).pom文件

(2).mybatis.xml文件

(3).pojo类

(4).数据库映射XML

(5).创建数据库操作对应的接口

(6).控制器

第一项,配置pom文件,需要加入两个maven包,一个是数据库连接驱动,一个是mybatis
xml 复制代码
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>8.0.31</version>
</dependency>
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.4.6</version>
</dependency>
第二项,添加mybatis.xml文件
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">
<configuration>
    <settings>
        <!--当返回行的所有列都是空时,MyBatis默认返回null-->
        <setting name="returnInstanceForEmptyRow" value="true"/>
	<!--显示sql语句-->
<setting name="logImpl" value="STDOUT_LOGGING"/>

    </settings>

    <environments default="development">

        <environment id="development">
            <!--使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域-->
            <transactionManager type="JDBC"/>
            <!-- mybatis提供了3种数据源类型,分别是:POOLED,UNPOOLED,JNDI -->
            <!-- POOLED 表示支持JDBC数据源连接池 -->
            <!-- UNPOOLED 表示不支持数据源连接池 -->
            <!-- JNDI 表示支持外部数据源连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/gxa"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- 映射文件方式1,一个一个的配置
        <mapper resource="cn/thinknovo/pojo/UserMapper.xml"/>-->
        <!-- 映射文件方式2,自动扫描包内的Mapper接口与配置文件 -->
        <package name="cn/thinknovo/pojo"/>
    </mappers>
</configuration>
第三项,pojo类,创建一个类名与数据库相同,属性名和数据库字段名相同的pojo对象。
第四项,数据库映射XML文件
java 复制代码
<?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 namespace="cn.thinknovo.pojo.UserMapper">
    <select id="selectUser" resultType="cn.thinknovo.pojo.User">
      select * from user;
   </select>

    <insert id="insertUser" parameterType="cn.thinknovo.pojo.User">
      insert into user values (#{id},#{username},#{password});
   </insert>
</mapper>
第五项,定义数据库操作接口,这里需要注意的是,mybatis以此接口为调用入口,通过此接口对应的方法来检查并对应mapper.xml文件中的增删改查
java 复制代码
public interface UserMapper {
    // 方法名、参数类型、返回类型要和mapper.xml文件中的id相同
    List<User> selectUser();
    void insertUser(User user);
}
第六项,创建控制器--测试
java 复制代码
public class MybatisConsole {
    public static void main(String[] args) {
        try {
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            SqlSession session = sqlSessionFactory.openSession();
            UserMapper userMapper = session.getMapper(UserMapper.class);
            List<User> userList = userMapper.selectUser();
            System.out.println(userList);
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

至此,基础脚手架搭建完成

3. Mapper.xml文件的注册和自动扫描

在mybatis.xml文件中,可以直接使用package的方式来完成自动扫描,这样以后就不需要一个个的添加mapper.xml文件了

xml 复制代码
<mappers>
        <!-- 映射文件方式1,一个一个的配置
        <mapper resource="cn/thinknovo/pojo/UserMapper.xml"/>-->
        <!-- 映射文件方式2,自动扫描包内的Mapper接口与配置文件 -->
        <package name="cn/thinknovo/pojo"/>
    </mappers>

4.解决后台提示找不到对应xml文件

Idea默认找不到对应的xml配置路径,在pom文件的build标签中,加入resource标签如下代码:

xml 复制代码
<resources>
  <resource>
    <directory>src/main/java</directory>
    <includes>
      <include>**/*.xml</include>
    </includes>
  </resource>
</resources>

5.两种处理操作数据库的方式

(1).通过session得到对应的Mapper接口对象,然后由此对象调用对应的操作方法,例如:

java 复制代码
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> userList = userMapper.selectUser();
System.out.println(userList);

(2).通过session直接调用接口中对应的操作方法

java 复制代码
// 第一个参数对应接口中的方法名
session.selectList("selectUser");

(PS:注意在这里接口文件和Mapper.xml文件是必须的,缺一不可,可以通过删除对应的文件来测试执行结果。)

6.关闭自动提交事务

这里注意,只有执行增、删、改的时候,才需要提交事务,查询是不需要事务的,在操作完对应的增删改之后,执行session.commit();

PS:注意,mybatis默认事务就关闭了自动提交,可以通过接口查看

7.Xml配置方式的增删改查

首先配置mapper.xml文件

java 复制代码
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.pojo.UserMapper">

<select id="selectUser" resultType="cn.thinknovo.pojo.User">
  select * from user;
</select>

 <insert id="insertUser" parameterType="cn.thinknovo.pojo.User">
   insert into user values (#{id},#{username},#{password});
</insert>

<update id="updateUser" parameterType="cn.thinknovo.pojo.User">
   update user set username=#{username},password=#{password} where id=#{id};
</update>

<delete id="deleteUser" parameterType="java.lang.String">
   delete from user where id=#{id};
</delete>
</mapper>

然后在修改接口代码

java 复制代码
public interface UserMapper {
    // 方法名、参数类型、返回类型要和mapper.xml文件中的id相同
    List<User> selectUser();
    void insertUser(User user);
    void updateUser(User user);
    void deleteUser(String id);
}

在控制器中调用接口中指定的四个方法,就可以完成基本的增删改查

在控制器中调用接口中指定的四个方法,就可以完成基本的增删改查

8.多参数传递

在项目中,多参数传递更多的是基于pojo对象,或者map结构传递,但是也可能有需要多个形式参数传递,比如这样:

java 复制代码
UserMapper.insertUserByPassword("think12345","54321");

这种情况,配置文件需要做对应的处理,改成下面的样子:

xml 复制代码
<insert id="insertUserByPassword" parameterType="java.lang.String">
    insert into user values(null,#{param1},#{param2});
</insert>

param1代表获取第一个形式参数,依次类推

param1代表获取第一个形式参数,依次类推

也可以这样:

xml 复制代码
<insert id="insertUserByPassword" parameterType="java.lang.String">
    insert into user values(null,#{arg0},#{arg1});
</insert>

arg0代表获取第一个形式参数,依次类推

arg0代表获取第一个形式参数,依次类推

如果有更多的这样的形式参数,就递增数字,比如第三个就是parma3或者arg2,在动态配置sql的时候,根据需要可以任意调换顺序,比如可以换成下面的效果:

xml 复制代码
<insert id="insertUserByPassword" parameterType="java.lang.String">
    insert into user values(null,#{arg1},#{arg0});
</insert>

arg0还是代表第一个参数,arg1还是代表第二个参数,不受影响。

arg0还是代表第一个参数,arg1还是代表第二个参数,不受影响。

还可以这样写:

在接口中声明方法

xml 复制代码
/**
* mybatis  把参数转换为 map 了,其中@Param("key") 参数内
容就是 map 的 value
* @param name
* @param pwd
* @return
*/
List<User> selByNamePwd(@Param("name") String
userName,@Param("pwd") String userPwd);

在 mapper.xml 中添加

#{} 里面写@Param("内容")参数中内容

xml 复制代码
<!-- 当多参数时,不需要写 parameterType -->
<select id=" selByNamePwd" resultType="User" >
select * from User where name=#{name} and  pwd=#{pwd}
</select>

9.Java中的Map结构传递

如果在项目中需要多参数传递,更建议大家使用java.util.map的结构传递,这也是大部分项目使用的方式,mybatis会根据key来对应获取value值,设置的传递类型还是parameterType,比如这样:

xml 复制代码
<insert id="insertUserByUserAndPassword" parameterType="map">
insert into user values(null,#{username},#{password});
</insert>

10.Map结构传递

如果要定义为map结构传递,需要在mybatis.xml中定义map的结构方式,比如这样:

xml 复制代码
<parameterMap id="userMap" type="cn.thinknovo.pojos.User">
    <parameter property="username" javaType="java.lang.String"/>
    <parameter property="password" javaType="java.lang.String"/>
</parameterMap>
	

这里的id就是map引入的名字,我们在传递参数类型设定为map以后就可以使用,比如:

xml 复制代码
<insert id="insertUserByUserAndPassword2" parameterMap="userMap" >
insert into user values(null,#{username},#{password});
</insert>

11.注解的使用

删除mapper.xml文件,然后在接口文件中通过注解的方式添加sql语句

java 复制代码
public interface UserMapper {
// 方法名、参数类型、返回类型要和mapper.xml文件中的id相同
@Select("select * from user")
List<User> selectUser();
@Insert("insert into user values (#{id},#{username},#{password})")
void insertUser(User user);
@Update("update user set username=#{username},password=#{password} where id=#{id}")
void updateUser(User user);
@Delete("delete from user where id=#{id}")
void deleteUser(String id);
}

注意,我们现在可以删除mybatis.xml中的mapper标签,我们也可以在mybatis.xml文件中添加的mapper标签,不再需要resource属性,而是class属性,如下:

xml 复制代码
<!-- 在配置文件中 关联包下的 接口类-->
 <mappers>
     <mapper class="c.thinknovo.mybatis3.UserMapper"/>
 </mappers>

12.动态SQL的if使用 -- 非常重要

根据不同的条件执行不同的结果

xml 复制代码
<select id="selectUser" resultType="cn.thinknovo.pojo.User" parameterType="cn.thinknovo.pojo.User">
      select * from user
   <if test="username != null">
      where username=#{username}
   </if>
</select>

在配置文件中添加动态的if语句,如果传递过来的user对象中,username不等于null,那么追加条件查询

13.动态SQL的where使用

如果我们有多个条件需要添加,但是有可能一个条件都不满足,那么这时候使用上面的方式就会出现问题,所以我们还需要在if外部添加一个where标签

xml 复制代码
<select id="selectUser" resultType="cn.thinknovo.pojo.User" parameterType="cn.thinknovo.pojo.User">
      select * from user
   <where>
      <if test="username != null">
         username=#{username}
      </if>
      <if test="password != null">
         and password=#{password}
      </if>
   </where>
</select>

可以看到,where包含了两个if,而第一个if中没有and,where标签会自动检查状态,如果标签返回的第一个匹配内容是以 and或or 开头的,则会自动删除and或者or ,然后再追加where

14.动态SQL的choose when使用

xml 复制代码
<select id="selectUser" resultType="cn.thinknovo.pojo.User" parameterType="cn.thinknovo.pojo.User">
      select * from user where password='888888'
<where>
   <choose>
      <when test="username != null">
         AND username=#{username}
      </when>
      <when test="password != null">
         AND password=#{password}
      </when>
      <otherwise>
         AND id=#{id}
      </otherwise>
   </choose>
<where>
</select>

Choose when 类似于java中的switch case,任中只会走一个,一般是在有一个条件固定的情况下,需要额外不确定的条件时,使用choose的方式

15.逆向工程mybatis-generator-maven-plugin

(1)首先修改pom文件为下面的内容,需要注意configurationFile标签是对应mybatis-generator的路径和文件名,修改为自己想要的,其余不做修改:
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.thinknovo</groupId>
  <artifactId>mybatis002</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>mybatis002 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.46</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>1.3.6</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>mybatis002</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.7.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.20.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>

​        <plugin>
​          <!--Mybatis-generator插件,用于自动生成Mapper和POJO-->
​          <groupId>org.mybatis.generator</groupId>
​          <artifactId>mybatis-generator-maven-plugin</artifactId>
​          <version>1.3.6</version>
​          <configuration>
​            <!--配置文件的位置-->
​            <configurationFile>src\main\resources\mybatis-generator-config.xml</configurationFile>
​            <verbose>true</verbose>
​            <overwrite>true</overwrite>
​          </configuration>
​          <executions>
​            <execution>
​              <id>Generate MyBatis Artifacts</id>
​              <goals>
​                <goal>generate</goal>
​              </goals>
​            </execution>
​          </executions>
​          <dependencies>
​            <dependency>
​              <groupId>org.mybatis.generator</groupId>
​              <artifactId>mybatis-generator-core</artifactId>
​              <version>1.3.6</version>
​            </dependency>
​          </dependencies>
​        </plugin>
​      </plugins>
​    </pluginManagement>
  </build>
</project>
(2)接着添加mybatis-generator-config.xml文件,注意修改
(1)classPathEntry为自己的数据库连接池jar包物理路径
(2)jdbcConnection为自己的数据库连接参数
(3)javaModelGenerator为实体类生成的位置 修改targetPackage和targetProject
(4)sqlMapGenerator为*Mapper.xml 文件的位置 修改targetPackage和targetProject
(5)javaClientGenerator为Mapper 接口文件的位置 修改targetPackage和targetProject
(6)table为表对应内容,多表就配置多个,tableName表名 domainObjectName类名

完整配置如下:

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>


​    <!-- 本地数据库驱动程序jar包的全路径 -->
​    <classPathEntry location="C:\Users\Administrator\.m2\repository\mysql\mysql-connector-java\5.1.46\mysql-connector-java-5.1.46.jar"/>

​    <!-- 指定mybatis版本 -->
​    <context id="context" targetRuntime="MyBatis3">
​        <commentGenerator>
​            <property name="suppressAllComments" value="false"/>
​            <property name="suppressDate" value="true"/>
​        </commentGenerator>

​        <!-- 数据库的相关配置 -->
​        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
​                        connectionURL="jdbc:mysql://localhost:3306/hiber"
​                        userId="root"
​                        password="thinknovo"/>

​        <!--指定生成的类型为java类型,避免数据库中number等类型字段 -->
​        <javaTypeResolver>
​            <property name="forceBigDecimals" value="false"/>
​        </javaTypeResolver>

​        <!-- 实体类生成的位置  修改targetPackage和targetProject-->
​        <javaModelGenerator targetPackage="cn.thinknovo.test" targetProject="src/main/java">
​            <property name="enableSubPackages" value="false"/>
​            <property name="trimStrings" value="true"/>
​        </javaModelGenerator>

​        <!-- *Mapper.xml 文件的位置  修改targetPackage和targetProject-->
​        <sqlMapGenerator targetPackage="cn.thinknovo.test" targetProject="src/main/java">
​            <property name="enableSubPackages" value="false"/>
​        </sqlMapGenerator>

​        <!-- Mapper 接口文件的位置  修改targetPackage和targetProject-->
​        <javaClientGenerator targetPackage="cn.thinknovo.test" targetProject="src/main/java"
​                             type="XMLMAPPER">
​            <property name="enableSubPackages" value="false"/>
​        </javaClientGenerator>

​        <!-- 相关表的配置 多表就配置多个  tableName表名  domainObjectName类名 -->
      <table tableName="user" domainObjectName="User" enableCountByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               enableUpdateByExample="false"/>
    </context>
</generatorConfiguration>
(3)接着在idea右上角,点击edit
(4)开始配置mybatis-generator-maven-plugin运行
(5)输入运行命令mybatis-generator:generate -e
(6)点击保存,现在可以看到一个运行方式了,点击运行就可以自动得到内容了
(7)运行生成对应的文件

16.一对一映射

类似于hibernate中的创建办法,模拟一个人员对应一个学号,创建两个pojo实体类,下面代码省略了set、get方法

(1)第一个类是Iren人员类

复制代码
public class Iren {
  private long id;
  private String renyuanname;
  private long xuehaoid;
  private Ixuehao ixuehao;  //  添加一个学号类的对象

(2)第二个类是Ixuehao学号类

复制代码
public class Ixuehao {
  private long id;
  private String xuehao;

(3)创建一个Irenmapper.xml文件

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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IrenMapper">
    <select id="selectIren" resultMap="getOneToOneMap">
        select t1.id,t1.renyuanname,t1.xuehaoid,t2.id,t2.xuehao
        from iren t1,ixuehao t2
        where t1.xuehaoid = t2.id;
    </select>
​    <resultMap id="getOneToOneMap" type="cn.thinknovo.mybatis.pojo.Iren">
​        <id property="id" column="id"/>
​        <result property="renyuanname" column="renyuanname"/>
​        <result property="xuehaoid" column="xuehaoid"/>
​        <association property="ixuehao" javaType="cn.thinknovo.mybatis.pojo.Ixuehao">
​            <id property="id" column="id"/>
​            <result property="xuehao" column="xuehao"/>
​        </association>
​    </resultMap>
</mapper>

PS:这里使用到了resultMap标签,此标签中创建一对一的映射关系,在其中的id标签代表主键,result标签代表普通字段,association标签代表映射关系类

PS:这里使用到了resultMap标签,此标签中创建一对一的映射关系,在其中的id标签代表主键,result标签代表普通字段,association标签代表映射关系类

(4)创建一个Irenmapper接口

java 复制代码
public interface IrenMapper {
    List<Iren> selectIren();
}

(5)创建一个Console测试

java 复制代码
public static void main(String[] args) {
    try {
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sqlSessionFactory.openSession(false);
        IrenMapper irenMapper = session.getMapper(IrenMapper.class); 
        List<Iren> list = irenMapper.selectIren();
        System.out.println(list.size());
        for(Iren iren : list) {
            System.out.println(iren.getRenyuanname());
            System.out.println(iren.getIxuehao().getXuehao());
        }
        session.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

(6)反向一对一处理

在Ixuehao类中创建Iren的对象,然后创建对应的Ixuehao的mapper接口和xml文件,在配置resultMap时,把前面配置的两个表的参数互换,就可以实现反向一对一。

xml 复制代码
<select id="selectIxuehao" resultMap="getOneToOneMap">
    select t1.id,t1.renyuanname,t1.xuehaoid,t2.id,t2.xuehao
    from iren t1,ixuehao t2
    where t1.xuehaoid = t2.id;
</select>
<resultMap id="getOneToOneMap" type="cn.thinknovo.mybatis.pojo.Ixuehao">
    <id property="id" column="id"/>
    <result property="xuehao" column="xuehao"/>
    <association property="iren" javaType="cn.thinknovo.mybatis.pojo.Iren">
        <id property="id" column="id"/>
        <result property="renyuanname" column="renyuanname"/>
        <result property="xuehaoid" column="xuehaoid"/>
    </association>
</resultMap>

17.一对多映射

基于班级和学生的关系建立映射,set、get方法省略

(1)第一个类是Iclass班级类

java 复制代码
public class Iclass {
  private long id;
  private String cname;
  private List<Istudent> list;   // 这个班级中所有的学生

(2)第二个类是Istudent学生类

java 复制代码
public class Istudent {
  private long id;
  private String sname;
  private long cid;

(3)创建IclassMapper.xml文件

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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IclassMapper">

    <select id="selectIclass" resultMap="getOneToManyMap">
	select t1.id,t1.cname,t2.id id2,t2.sname,t2.cid
        from iclass t1,istudent t2
        where t1.id = t2.cid and t1.id=4;
    </select>

​    <resultMap id="getOneToManyMap" type="cn.thinknovo.mybatis.pojo.Iclass">
​        <id property="id" column="id"/>
​        <result property="cname" column="cname"/>
​        <collection property="list" ofType="cn.thinknovo.mybatis.pojo.Istudent">
​            <id property="id" column="id2"/>
​            <result property="sname" column="sname"/>
​            <result property="cid" column="cid"/>
​        </collection>
​    </resultMap>
</mapper>

PS:这里注意的是,一对多使用的collection标签,并且mybatis自身bug,导致,当两张表的主键同名时,list中只有一个对象,解决这个问题的办法是把其中一个主键id改一个别名

PS:这里注意的是,一对多使用的collection标签,并且mybatis自身bug,导致,当两张表的主键同名时,list中只有一个对象,解决这个问题的办法是把其中一个主键id改一个别名

(4)创建一个Iclassmapper接口

java 复制代码
public interface IclassMapper {
    Iclass selectIclass();
}

(5)创建一个Console测试

java 复制代码
public static void main(String[] args) {
    try {
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sqlSessionFactory.openSession(false);
        IclassMapper iclassMapper = session.getMapper(IclassMapper.class);
        Iclass iclass = iclassMapper.selectIclass();
        System.out.println(iclass.getCname());
        System.out.println(iclass.getList());
        for(Istudent istudent : iclass.getList()) {
            System.out.println(istudent.getSname());
        }
        session.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

(6)反向多对一处理

在mybatis里面其实没有多对一的说法,多对一只能看做是一对一,所以我们需要在Istudent中增加Iclass对象:

java 复制代码
public class Istudent {
  private long id;
  private String sname;
  private long cid;
  private Iclass iclass;  // 增加班级对象

创建一个IstudentMapper.xml文件:

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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IstudentMapper">

  <select id="selectIstudent" resultMap="getOneToOneMap">
        select t1.id,t1.cname,t2.id id2,t2.sname,t2.cid
        from iclass t1,istudent t2
        where t1.id = t2.cid and t2.id=2;
    </select>

​    <resultMap id="getOneToOneMap" type="cn.thinknovo.mybatis.pojo.Istudent">
​        <id property="id" column="id2"/>
​        <result property="sname" column="sname"/>
​        <result property="cid" column="cid"/>
​        <association property="iclass" javaType="cn.thinknovo.mybatis.pojo.Iclass">
​            <id property="id" column="id"/>
​            <result property="cname" column="cname"/>
​        </association>
​    </resultMap>
</mapper>

PS:这里使用到的是一对一的处理法则,所以使用的一对一的标签association

PS:这里使用到的是一对一的处理法则,所以使用的一对一的标签association

然后创建IstudentMapper接口,编写测试类完成,这里省略...

18.多对多映射

还是基于订购商品操作,一个用户可以对应多个商品,一个商品可以对应多个订单,其实在mybatis实现多对多映射操作,类似于一对多映射,只是SQL编写的相对复杂一些,因为涉及到了中间表。

(1)第一个类是Ishangpin商品的类

复制代码
public class Ishangpin {
  private long id;
  private String shangpinname;
  private List<Igoumai> list;        // list代表多个购买者

(2)第二个类是Igoumai购买者的类

复制代码
public class Igoumai {
  private long id;
  private String goumainame;

(3)创建IshangpinMapper.xml文件

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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IshangpinMapper">

    <select id="selectIshangpin" resultMap="getManyToManyMap">
        select
            t1.shangpinid,
            t1.goumaiid,
            t2.id,
            t2.goumainame,
            t3.id id2,
            t3.shangpinname
        from
            idingdan t1,
            igoumai t2,
            ishangpin t3
        where t1.goumaiid=t2.id and t1.shangpinid=t3.id and t1.shangpinid=6;
    </select>

​    <resultMap id="getManyToManyMap" type="cn.thinknovo.mybatis.pojo.Ishangpin">
​        <id property="id" column="id2"/>
​        <result property="shangpinname" column="shangpinname"/>
​        <collection property="list" ofType="cn.thinknovo.mybatis.pojo.Igoumai">
​            <id property="id" column="id"/>
​            <result property="goumainame" column="goumainame"/>
​        </collection>
​    </resultMap>
</mapper>

PS:这个配置文件中有多处需要注意的地方,1.查看SQL的编写,三表关联查询;2.resultMap中涉及的还是collection标签;3.两张表的id主键的名字不能相同,必须保证其中一个是别名

PS:这个配置文件中有多处需要注意的地方,1.查看SQL的编写,三表关联查询;2.resultMap中涉及的还是collection标签;3.两张表的id主键的名字不能相同,必须保证其中一个是别名

(4)创建一个IshangpinMapper接口

java 复制代码
public interface IshangpinMapper {
    List<Ishangpin> selectIshangpin();
}

(5)创建一个Console测试

java 复制代码
IshangpinMapper ishangpinMapper = session.getMapper(IshangpinMapper.class);
List<Ishangpin> list = ishangpinMapper.selectIshangpin();
System.out.println(list);
System.out.println(list.get(0).getShangpinname());
System.out.println(list.get(0).getList());
System.out.println(list.get(0).getList().get(0).getGoumainame());

(6)反向多对多处理

原理和上述一致,只需要在购买者中的增加商品的list,并且配置购买者的mapper接口和XML文件即可。

19.缓存

一级缓存SqlSession

  1. 应用程序和数据库交互的过程是一个相对比较耗时的过程
  2. 缓存存在的意义:让应用程序减少对数据库的访问,提升程序运行效率
  3. MyBatis 中默认 SqlSession 缓存开启
    3.1 同一个 SqlSession 对象调用同一个时,只有第一次访问数据库,第一次之后把查询结果缓存到SqlSession缓存区(内存)中
    3.2 缓存的是 statement 对象.(简单记忆必须是用一个是用一个),在 myabtis 时一个对应一个 statement 对象
    3.3 有效范围必须是同一个 SqlSession 对象
    缓存流程:
    步骤一: 先去缓存区中找是否存在 statement
    步骤二:返回结果
    步骤三:如果没有缓存 statement 对象,去数据库获取数据
    步骤四:数据库返回查询结果
    步骤五:把查询结果放到对应的缓存区中

二级缓存SqlSessionFactory 缓存

有效范围:同一个 factory 内哪个 SqlSession 都可以获取

什么时候使用二级缓存:当数据频繁被使用,很少被修改

使用二级缓存步骤:

步骤一:在 mapper.xml 中添加

步骤二:如果不写 readOnly="true"需要把实体类序列化

<cache readOnly=" true"></ cache >

步骤三:当 SqlSession 对象 close()时或 commit()时会把 SqlSession 缓存的数据刷(flush)到 SqlSessionFactory 缓存区中

ngpin();

System.out.println(list);

System.out.println(list.get(0).getShangpinname());

System.out.println(list.get(0).getList());

System.out.println(list.get(0).getList().get(0).getGoumainame());

复制代码
(6)反向多对多处理
原理和上述一致,只需要在购买者中的增加商品的list,并且配置购买者的mapper接口和XML文件即可。

## 缓存

### 一级缓存SqlSession

1. 应用程序和数据库交互的过程是一个相对比较耗时的过程 
2. 缓存存在的意义:让应用程序减少对数据库的访问,提升程序运行效率
3. MyBatis 中默认 SqlSession 缓存开启
3.1 同一个 SqlSession 对象调用同一个<select>时,只有第一次访问数据库,第一次之后把查询结果缓存到SqlSession缓存区(内存)中
3.2 缓存的是 statement 对象.(简单记忆必须是用一个是用一个<select>),在 myabtis 时一个<select>对应一个 statement 对象
3.3 有效范围必须是同一个 SqlSession 对象
缓存流程:
步骤一: 先去缓存区中找是否存在 statement
步骤二:返回结果
步骤三:如果没有缓存 statement 对象,去数据库获取数据
步骤四:数据库返回查询结果
步骤五:把查询结果放到对应的缓存区中

### 二级缓存SqlSessionFactory 缓存

有效范围:同一个 factory 内哪个 SqlSession 都可以获取
什么时候使用二级缓存:当数据频繁被使用,很少被修改
使用二级缓存步骤:
步骤一:在 mapper.xml 中添加
步骤二:如果不写 readOnly="true"需要把实体类序列化
<cache readOnly=" true"></ cache >
步骤三:当 SqlSession 对象 close()时或 commit()时会把 SqlSession 缓存的数据刷(flush)到 SqlSessionFactory 缓存区中
相关推荐
考虑考虑14 小时前
Jpa使用union all
java·spring boot·后端
用户37215742613514 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊15 小时前
Java学习第22天 - 云原生与容器化
java
渣哥17 小时前
原来 Java 里线程安全集合有这么多种
java
间彧17 小时前
Spring Boot集成Spring Security完整指南
java
间彧17 小时前
Spring Secutiy基本原理及工作流程
java
Java水解19 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆21 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学21 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole21 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端