Mybatis


MyBatis

框架

软件的半成品

Mybatis概述

是一个持久层框架,使用sql语句将实体类映射到数据表,是一个半自动的ORM实现

O:对象

R:关系型数据库

M:映射(自动映射)

Hibernate:全自动的ORM实现

SSH:Struts2、Spring,Hibernate

SSM:SpringMVC、Spring、MyBatis

历史

最早是apache的一个开源项目iBatis,2010年更名为mybatis

特点

外部化sql语句:把sql语句与java代码分离

封装化sql语句:把sql语句封装到单独的文件总,方便管理

使用

  1. 创建一个maven项目

  2. 配置 pom.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>org.neu</groupId>
        <artifactId>maven-demo</artifactId>
        <packaging>war</packaging>
        <version>1.0-SNAPSHOT</version>
    
        <build>
            <plugins>
                <!-- 资源文件拷贝插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>2.7</version>
                    <configuration>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
                <!-- java编译插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.2</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>            
            </plugins>
            <resources>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.xml</include>
                    </includes>
                </resource>
                <resource>
                    <directory>src/main/resources</directory>
                </resource>
            </resources>
        </build>
    
        <!-- 依赖 -->
        <dependencies>
            <!-- 单元测试 -->
            <!-- https://mvnrepository.com/artifact/junit/junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
            
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.6</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.22</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.20</version>
                <scope>provided</scope>
            </dependency>
    
        </dependencies>
    </project>
    
  3. 在resources目录下,添加SqlMapConfig.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>
        <!-- 配置一个环境,一个环境对应着一个数据库,default为某一个环境的id -->
        <environments default="mysql">
            <environment id="mysql">
                <!-- 事务管理器,jdbc/managed(由外部容器管理,自己什么也不做) -->
                <transactionManager type="jdbc"></transactionManager>
                <!-- 数据源,unpooled、pooled、jndi -->
                <dataSource type="pooled">
                    <property name="url" value="jdbc:mysql://localhost:3306/java15?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai"/>
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
            <package name="com.neu.mapper"></package>
        </mappers>
    </configuration>
    
  4. Mapper映射文件

    • 编写实体类

    • 创建一个包:com.neu.mapper

    • 在Mapper包下,创建接口:DeptMapper,在该接口中添加增删改查的方法

    • 使用mybatis mapper向导,生成接口的配置映射文件:配置文件的名与接口名相同

    • 在生成的映射文件中(DeptMapper.xml),namespace的名称为对应的接口的完全限定名(包名+接口名)

    • statement的id与接口中的方法名相同

    • 如果statement为select类型,必须添加一个 resultType 或 resultMap 属性,resultType的值必须为方法返回值中实体类型名

    • 注册 mapper(SqlMapConfig.xml)

      <mappers>
              <!-- <mapper resource="com/neu/mapper/DeptMapper.xml" />	 -->
              <!-- <mapper class="com.neu.mapper.DeptMapper"/> -->
              <package name="com.neu.mapper"></package>
      </mappers>
      
  5. 改进后的测试代码

    package com.neu.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    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 org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.neu.mapper.DeptMapper;
    import com.neu.po.Dept;
    
    public class DeptMapperTest {
        private DeptMapper deptMapper;
        private SqlSession sqlSession;
        
        @Before
        public void setup() throws IOException {
            //读取SqlMapConfig.xml文件
            InputStream resource = Resources.getResourceAsStream("SqlMapConfig.xml");
            //创建SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resource);
            //得到Sqlsession对象(相当于数据库连接)
            sqlSession = sqlSessionFactory.openSession();
            //得到DeptMapper接口的实现类
            deptMapper = sqlSession.getMapper(DeptMapper.class);
        }
        
        @After
        public void after() {
            //关闭sqlSession,把连接放回到连接池
            sqlSession.close();
        }
        
        @Test
        public void testInsert() throws IOException {		
            int n = deptMapper.insert(new Dept(66,"hr","sy"));
            
            System.out.println(n);
            //提交事务
            sqlSession.commit();		
        }
        
        @Test
        public void testUpdate() throws IOException {	
            int n = deptMapper.update(new Dept(66,"hr","nj"));
            
            System.out.println(n);
            //提交事务
            sqlSession.commit();		
        }
        
        @Test
        public void testDelete() throws IOException {	
            int n = deptMapper.delete(66);
            
            System.out.println(n);
            //提交事务
            sqlSession.commit();		
        }
        
        @Test
        public void testGetById() throws IOException {	
            Dept dept = deptMapper.getById(10);
            
            System.out.println(dept);			
        }
        
        @Test
        public void testGetAll() throws IOException {	
            List<Dept> list = deptMapper.getAll();
            
            System.out.println(list);			
        }
    }
    

作业

实现 Emp 的增删改查方法

使用log4j生成日志

添加依赖

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

拷贝log4j.properties配置文件到resources下

# Global logging configuration
#\u751F\u4EA7\u73AF\u5883\u914D\u7F6Einfo   ERROR
log4j.rootLogger=DEBUG,stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

多参数的处理

  1. 使用参数名:arg0、arg1…

    <select id="search" resultType="com.neu.po.Dept">
            select * from dept where dname = #{arg0} and loc = #{arg1}
    </select>
    
  2. 使用参数名:param1、param2

    <select id="search" resultType="com.neu.po.Dept">
            select * from dept where dname = #{param1} and loc = #{param2}
    </select>
    
  3. 使用@Param注解(推荐)

    接口:
    List<Dept> search(@Param("dname") String dname,@Param("loc") String loc);
    mapper:
    select * from dept where dname = #{dname} and loc = #{loc}
    
  4. 使用实体类封装多个参数

    接口:
    List<Dept> search2(Dept dept);
    
    mapper:
    select * from dept where dname = #{dname} and loc = #{loc}
    
    测试代码:
    List<Dept> list = deptMapper.search2(new Dept(null,"hr","sy"));
    
  5. 使用map集合,封装多个参数(很灵活)

    接口:
    List<Dept> search3(Map<String, String> map);
    
    mapper:
    select * from dept where dname = #{dname} and loc = #{loc}
    
    测试代码:
    Map map = new HashMap<>();
    map.put("dname", "hr");
    map.put("loc", "sy");
            
    List<Dept> list = deptMapper.search3(map);
    

#{}和${}

  1. #{}:使用占位符的方式生成sql语句,sql语句中列名为变量的时候,不能使用

  2. ${}:使用拼接字符串的方式生成sql语句,参数为列名的时候,可以使用

    接口:
    //根据参数列名来排序
    List<Dept> order(String columnName);
    
    mapper:
    select * from dept order by ${columnName}
    
  3. 模糊查询

    • 使用#{}

      接口:
      List<Dept> search4(String dname);
      
      mapper:
      select * from dept where dname like #{dname}
      
      测试代码:
      List<Dept> list = deptMapper.search4("%h%");
      
    • 使用${}

      接口:
      List<Dept> search4(String dname);
      
      mapper:
      select * from dept where dname like '%${dname}%'
      
      测试代码:
      List<Dept> list = deptMapper.search4("h");
      

动态SQL

  1. <if test="表达式">sql片段</if>

    当表达式为true的时候,输出sql片段,否则不输出

    List<Dept> find(Dept dept);
    
    mapper:
    <select id="find" resultType="com.neu.po.Dept">
            select * from dept 
            where 1 = 1
            <if test="deptno != null">
                and deptno = #{deptno}
            </if>
            <if test="dname != null">
                and dname = #{dname}
            </if>
            <if test="loc != null">
                and loc = #{loc}
            </if>
    </select>
    
  2. <trim prefix="前缀" prefixOverrides="被覆盖的前缀" suffixOverrides="被覆盖的后缀"></trim>

    prefix:如果trim标签中内容不为空串,则添加该前缀,如果内容为空串,则不添加

    prefixOverrides:如果trim标签内容最前面的部分是该属性的内容,则覆盖掉

    suffixOverrides:如果trim标签内容最后面的部分是该属性的内容,则覆盖掉

    <select id="find" resultType="com.neu.po.Dept">
            select * from dept 
            <trim prefix="where" prefixOverrides="and">
                <if test="deptno != null">
                    and deptno = #{deptno}
                </if>
                <if test="dname != null">
                    and dname = #{dname}
                </if>
                <if test="loc != null">
                    and loc = #{loc}
                </if>
            </trim>
    </select>
    
    <update id="update2">
            update dept 
            <trim prefix="set" suffixOverrides=",">
                <if test="dname != null" >
                    dname = #{dname},
                </if>
                <if test="loc != null" >
                    loc = #{loc}
                </if>
            </trim>
            where deptno = #{deptno}
        </update>
    
  3. <where></where>,相当于:<trim prefix="where" prefixOverrides="and">

    <select id="find" resultType="com.neu.po.Dept">
            select * from dept 
            <where>
                <if test="deptno != null">
                    and deptno = #{deptno}
                </if>
                <if test="dname != null">
                    and dname = #{dname}
                </if>
                <if test="loc != null">
                    and loc = #{loc}
                </if>
            </where>
    </select>
    
  4. <set></set>相当于:<trim prefix="set" suffixOverrides=",">

    <update id="update2">
            update dept 
            <set>
                <if test="dname != null" >
                    dname = #{dname},
                </if>
                <if test="loc != null" >
                    loc = #{loc}
                </if>
            </set>
            where deptno = #{deptno}
    </update>
    
  5. <foreach></foreach>:用来处理集合和数组

    collection:list|conllection|array

    item:引用集合或数组中的当前遍历元素

    separator:分隔符

    接口:
    int batchInsert(List<Dept> list);
    
    mapper:
    <insert id="batchInsert">
            insert into dept values
            <foreach collection="list" item="dept" separator=",">
                (#{dept.deptno},#{dept.dname},#{dept.loc})
            </foreach>
    </insert>
    

    open:要添加的开始字符串

    close:要添加的结束字符串

    接口:
    int batchDelete(int[] ids);
    
    mapper:
    <delete id="batchDelete">
            delete from dept where deptno in
            <foreach collection="array" item="deptno" separator="," open="(" close=")">
                #{deptno}
            </foreach>
    </delete>
    

    练习:编写Emp的动态sql

SQL片段

  1. 定义:用来定义可以重复使用的sql代码段,可以包含在其他sql语句中

  2. 使用:

    • 定义sql片段

      <sql id="selectAll">
          select * from dept
      </sql>
      
    • 引用sql片段

      <include refid="selectAll"></include>
      

得到插入的主键值

<selectKey>:

  • order:决定了查询语句执行的先后

    • after:先执行插入语句,后执行查询主键的sql语句(mysql)
    • before:先执行查询(生成)主键值的语句,再执行插入语句(oracle)
  • keyProperty:键属性名,查询得到的主键值放到形参的哪个属性中

  • resultType:查询的主键值的类型

使用:

<insert id="insert">
        <selectKey order="AFTER" keyProperty="deptno" resultType="int">
            select last_insert_id()
        </selectKey>
        insert into dept values(null,#{dname},#{loc})
</insert>

查询返回简单数据类型

简单数据类型:基本数据类型(8种)、对应的包装类、String

接口:
//根据部门编号得到部门名称
String getDname(int deptno);

mapper:
<select id="getDname" resultType="string">
        select dname from dept where deptno = #{deptno}
</select>
//得到部门总数
int count();

<select id="count" resultType="int">
    select count(*) from dept
</select>

返回boolean类型:如果查询的记录数>0,返回:true,等于0,返回:false

//判断名称为参数执行的部门是否存在
boolean exist(String dname);

<select id="exist" resultType="boolean">
    select count(*) from dept where dname = #{dname}
</select>

分页

//pageNum:第几页,pageSize:每页最多有多少行
List<Dept> getPaged(@Param("pageNum") int pageNum,@Param("pageSize") int pageSize);

<select id="getPaged" resultType="com.neu.po.Dept">
    select * from dept 
    limit ${(pageNum - 1) * pageSize},#{pageSize}
</select>

列名与属性名不一致

  1. 在sql语句中,为列起别名,别名与属性名一致

    select deptno,dname dname2,loc from dept
    
  2. 使用<resultMap>来进行映射

    <resultMap type="com.neu.po.Dept" id="basicMap">
            <!-- <id column="deptno" property="deptno"/> -->
            
            <result column="dname" property="dname2"/>
            <!-- <result column="loc" property="loc"/> -->
    </resultMap>
    
    <select id="getById" resultMap="basicMap">
            <include refid="selectAll"></include> where deptno = #{no}
    </select>
    

    <id>:用来映射标识列(数据库中的主键)

    <result>:用来映射普通的结果(非主键)

    column:列名

    property:属性名

实体关联

<association>:关联(实体),表示一对一的关系(emp=》dept)

//Emp实体类
...
Dept dept;
mapper:

<mapper namespace="com.neu.mapper.EmpMapper">
    <resultMap type="com.neu.po.Emp" id="basicMap">
        <id column="empno" property="empno" ></id>
        <result column="ename" property="ename"/>
        <result column="job" property="job"/>
        <result column="hiredate" property="hiredate"/>
        <result column="sal" property="sal"/>
        <result column="mgr" property="mgr"/>
        <result column="comm" property="comm"/>
        
        <association property="dept" javaType="com.neu.po.Dept">
            <id column="deptno" property="deptno"/>
            <result column="dname" property="dname2"/>
            <result column="loc" property="loc"/>
        </association>
    </resultMap>

    <select id="getById" resultMap="basicMap">
        SELECT e.*,dname,loc 
        FROM dept d JOIN emp e 
        ON d.deptno = e.deptno
        where empno = #{empno}
    </select>
</mapper>
<resultMap type="com.neu.po.Dept" id="basicMap">
        <id column="deptno" property="deptno" />
        <result column="dname" property="dname1"/>
        <result column="loc" property="loc"/>
        
        <collection property="emps" ofType="com.neu.po.Emp">
            <id column="empno" property="empno"/>
            <id column="ename" property="ename"/>
            <id column="job" property="job"/>
            <id column="hiredate" property="hiredate"/>
            <id column="sal" property="sal"/>
            <id column="comm" property="comm"/>
            <id column="mgr" property="mgr"/>
        </collection>
    </resultMap>


    <select id="getById" resultMap="basicMap">
        select d.dname,d.loc,e.* from dept d left join emp e 
        on d.deptno = e.deptno 
         WHERE e.deptno = #{deptno}
    </select>

实体关联的第二种实现方法:再执行一次查询,根据已有的列查询出需要的对象

<mapper namespace="com.neu.mapper.EmpMapper">
    <resultMap type="com.neu.po.Emp" id="basicMap">		
        <!-- column的值为emp表中的列名 -->
        <association property="dept" column="deptno" select="com.neu.mapper.DeptMapper.getById">			
        </association>
    </resultMap>

    <select id="getById" resultMap="basicMap">
        SELECT * FROM emp where empno = #{empno}
    </select>
</mapper>

关联集合

<collection>:关联集合,表示一对多的关系(dept=》List

<resultMap type="com.neu.po.Dept" id="basicMap">
        <id column="deptno" property="deptno"/>
        
        <result column="dname" property="dname2"/>
        <!-- <result column="loc" property="loc"/> -->
        <!-- column列的值为:Dept表中的deptno -->
        <collection property="emps" column="deptno" select="com.neu.mapper.EmpMapper.getByDeptno"></collection>
</resultMap>

练习

CREATE TABLE role(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(30) NOT NULL
) CHARSET=utf8;

INSERT INTO role VALUES(1,'管理员');
INSERT INTO role VALUES(2,'普通用户');

CREATE TABLE myuser(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(30) NOT NULL,
    roleId INT NOT NULL
) CHARSET=utf8;

INSERT INTO myuser VALUES(1,'tom',1);
INSERT INTO myuser VALUES(2,'scott',2);
INSERT INTO myuser VALUES(3,'marry',2);

功能:

  1. 查询所有用户的信息(包括用户的角色信息)
  2. 根据角色名称查询该角色的信息及该角色下的所有用户信息

使用注解替代Mapper文件

  1. 使用注解

    @Update("update dept set dname = #{dname2} ,loc = #{loc} where deptno = #{deptno}")
    int update(Dept dept);
    
  2. 长sql语句的写法

    @Update("update dept set dname = #{dname2} ,loc = #{loc} "+
            "where deptno = #{deptno}")
    int update(Dept dept);
    
    @Update({"update dept set dname = #{dname2} ,loc = #{loc} ",
              "where deptno = #{deptno}"})
    int update(Dept dept);
    
  3. ResultMap(mybatis 3.5.4)

    @Select("select * from dept where deptno = #{deptno}")
    @Results(id = "basicMap",value= {
                @Result(column = "deptno",property = "deptno",id = true),
                @Result(column = "dname",property = "dname2",id = false),
                @Result(column = "loc",property = "loc",id = false),
                @Result(column = "deptno",property = "emps",many=@Many(select = "com.neu.mapper.EmpMapper.getByDeptno"))
                
        })
    Dept getById(int deptno);
    

延迟加载

  1. 定义:在数据与对象进行mapping操作时,只有在真正使用该对象的时候,才进行mapping操作,以减少数据库开销,从而提高系统性能

  2. 默认情况下,mybatis没有开启延迟加载功能,如果要开启,需要配置SqlMapConfig.xml文件

    <settings>
            <!-- 开启延迟加载 -->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!-- 取消积极加载 -->
            <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    

缓存

  1. 定义:是一种“以空间换时间”的设计理念,利用内存或硬盘空间来提高数据检索速度的有效手段之一。

  2. 一级缓存:默认开启,把数据缓存到当前会话中(SqlSession)

    @Test
    public void testGetById() throws IOException {	
        Dept dept = deptMapper.getById(10);
        System.out.println(dept.getDname2());
    
        dept = deptMapper.getById(10);
        System.out.println(dept.getDname2());
    }
    
  3. 二级缓存:默认没有开启,需要手工开启,修改SqlMapConfig.xml文件,把数据缓存到SqlSessionFactory中

    <!-- 开启二级缓存 -->
    <setting name="cacheEnabled" value="true"/>
    

    在需要缓存的mapper文件中:

    <cache></cache>
    

    注意:缓存对象要实现可序列化接口(Serializable)

MBG

  1. 定义:是一个MyBatis的代码生成器,是根据已经创建的数据库表生成实体类、mapper接口、sql映射文件

  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>
        <context id="context1" targetRuntime="Mybatis3Simple">
          <jdbcConnection connectionURL="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8" driverClass="com.mysql.jdbc.Driver" password="root" userId="root" />
          <javaModelGenerator targetPackage="com.neu.po" targetProject="mybatisdemo2" />
          <sqlMapGenerator targetPackage="com.neu.mapper" targetProject="mybatisdemo2"></sqlMapGenerator>
          <javaClientGenerator targetPackage="com.neu.mapper" targetProject="mybatisdemo2" type="XMLMAPPER" />   
          
          <table schema="root" tableName="dept">
            <!-- <columnOverride column="???" property="???" /> -->
          </table>
        </context>
      </generatorConfiguration>
      

排序:

example.setOrderByClause("ename desc");

Example练习

  1. 查询员工姓名等于“smith”并且sal大于等于3000的员工信息
  2. 查询员工编号为:7783和7876的员工信息
  3. 查询奖金(comm)不是null的所有员工信息
  4. 更新员工编号为7783的薪水,薪水增加200元
  5. 查询工资小于2000元或部门编号为10的所有员工信息
  6. 根据部门名称查询该部门所有员工(组合DeptExample和EmpExample查询)

Idea 中使用 Free mybatis plugin

配置数据源

  1. 在idea中连接数据库

    • 添加数据源,选mysql
    • 配置数据库连接参数

    • 在Advanced 中 配置 serverTimezone:Asia/Shanghai

    • 测试连接

    • 查看数据表

生成代码

  1. 选择表

  2. 输入参数

Idea环境中pom.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>com.neu</groupId>
    <artifactId>maven-demo3</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <!-- 资源文件拷贝插件 -->
            <!--<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.7</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>-->
            <!-- java编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
        <!--<resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>-->
    </build>
    <!-- 依赖 -->
    <dependencies>
        <!-- 单元测试 -->
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
</project>

Idea中代码生成

方法一

  1. 创建 maven 项目,导入依赖和插件

    <?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>com.neu</groupId>
        <artifactId>mbgdemo</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <!--<dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.22</version>
            </dependency>-->
        </dependencies>
    
        <build>
            <plugins>
                <!--mybatis-generator插件-->
                <plugin>
                    <!--Mybatis-generator插件,用于自动生成Mapper和POJO-->
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>1.3.2</version>
                    <configuration>
                        <!--配置文件的位置  一定要改成配置文件的位置-->
                        <configurationFile>src/main/resources/generatorConfig.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.2</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
  2. 在 src/main/resources/ 创建文件: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>
      <classPathEntry location="D:\mavenrepository\mysql\mysql-connector-java\8.0.22\mysql-connector-java-8.0.22.jar"/>
      <context id="context1" targetRuntime="Mybatis3">
        <jdbcConnection 
            connectionURL="jdbc:mysql://localhost:3306/his_java15?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai" 
            driverClass="com.mysql.cj.jdbc.Driver" 
            password="root" 
            userId="root" >
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>
        <!-- 实体类 -->
        <javaModelGenerator targetPackage="com.neu.po" targetProject="src/main/java" />
        <!-- 生成Mapper.xml -->
        <sqlMapGenerator targetPackage="com.neu.mapper" targetProject="src/main/resources"></sqlMapGenerator>
        <!-- java的Mapper接口 -->
        <javaClientGenerator targetPackage="com.neu.mapper" targetProject="src/main/java" type="XMLMAPPER" />
        
        
        <table schema="root" tableName="role">
            <generatedKey column="id" sqlStatement="mysql" identity="true"/>      
        </table>
          <!--
          <table schema="root" tableName="user">
              <generatedKey column="id" sqlStatement="mysql" identity="true"/>
    
              <columnOverride column="useType" property="role" javaType="Role" />
          </table>
          -->
        
        <!--<table schema="root" tableName="Department" domainObjectName="Department">
            <generatedKey column="id" sqlStatement="mysql" identity="true"/>  
            
            <columnOverride column="DeptCode" property="deptCode"></columnOverride>
            <columnOverride column="DeptName" property="deptName"></columnOverride>
            <columnOverride column="DeptCategoryID" property="deptCategory" javaType="ConstantItem"></columnOverride>
            <columnOverride column="DeptType" property="deptType" javaType="ConstantItem"></columnOverride>
            <columnOverride column="DelMark" property="delMark"></columnOverride>
        </table>-->
      </context>
    </generatorConfiguration>
    
  3. 生成代码

方法二

  1. 使用 MyBatisCodeHelpPro 插件,生成 xml配置文件

  2. 修改 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>
        <classPathEntry location="D:\mavenrepository\mysql\mysql-connector-java\8.0.22\mysql-connector-java-8.0.22.jar"/>
    
        <context id="Mybatis3Context" targetRuntime="MyBatis3">
            <property name="javaFileEncoding" value="UTF-8"/>
            <jdbcConnection
                    connectionURL="jdbc:mysql://localhost:3306/his_java15?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai"
                    driverClass="com.mysql.cj.jdbc.Driver"
                    password="root"
                    userId="root" >
                <property name="nullCatalogMeansCurrent" value="true"/>
            </jdbcConnection>
    
            <javaTypeResolver>
                <property name="forceBigDecimals" value="false"/>
            </javaTypeResolver>
    
            <javaModelGenerator targetPackage="com.neu.po" targetProject="src/main/java">
                <property name="enableSubPackages" value="true"/>
                <property name="trimStrings" value="true"/>
            </javaModelGenerator>
    
            <sqlMapGenerator targetPackage="com.neu.mapper" targetProject="src/main/resources">
                <property name="enableSubPackages" value="true"/>
            </sqlMapGenerator>
    
            <javaClientGenerator type="XMLMAPPER" targetPackage="com.neu.mapper" targetProject="src/main/java">
                <property name="enableSubPackages" value="true"/>
            </javaClientGenerator>
    
            <table schema="root" tableName="role">
                <generatedKey column="id" sqlStatement="mysql" identity="true"/>
            </table>
    
        </context>
    </generatorConfiguration>
    
  3. 修改 pom.xml文件,添加 maven 插件

    <?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>com.neu</groupId>
        <artifactId>mgb2</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <build>
            <plugins>
                <!--mybatis-generator插件-->
                <plugin>
                    <!--Mybatis-generator插件,用于自动生成Mapper和POJO-->
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>1.3.2</version>
                    <configuration>
                        <!--配置文件的位置  一定要改成配置文件的位置-->
                        <configurationFile>src/main/resources/MybatisGenerator.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.2</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    </project>
    
  4. 生成代码(同方法一)

Idea中生成Mapper

  1. 在 mapper 接口上 alt + enter

  2. 选择:Generate mapper of xml

  3. 选择mapper 位置

MyBatis中TypeHandler

在Mybatis中可以定义一个TypeHandler类型,通过它可以实现Java类型跟数据库类型的相互转换。

需求:把java实体类中的String[],转换为数据库中的varchar类型(例如保存用户的多个爱好) 

  1. 数据库

    CREATE TABLE myuser(
        id INT PRIMARY KEY AUTO_INCREMENT,
        username VARCHAR(30) NOT NULL,
        PASSWORD VARCHAR(30) NOT NULL,
        interests VARCHAR(100) 
    )
    
  2. 实体类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class MyUser {
        private int id;  
        private String username;  
        private String password;  
        private String[] interests;
    }
    
  3. 类型转换器

    package com.neu.util;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Date;
    
    import org.apache.ibatis.type.BaseTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    import org.apache.ibatis.type.MappedJdbcTypes;
    import org.apache.ibatis.type.MappedTypes;
    
    @MappedJdbcTypes(JdbcType.VARCHAR)
    @MappedTypes(String[].class)
    public class StringArrayTypeHandler extends BaseTypeHandler<String[]> {
    
        private String[] getStringArray(String columnValue) {
           if (columnValue == null)
               return null;
           return columnValue.split(",");
        }
         
        @Override
        public String[] getNullableResult(ResultSet rs, String columnName)
               throws SQLException {
           return getStringArray(rs.getString(columnName));
        }
     
        @Override
        public String[] getNullableResult(ResultSet rs, int columnIndex)
               throws SQLException {
           return this.getStringArray(rs.getString(columnIndex));
        }
     
        @Override
        public String[] getNullableResult(CallableStatement cs, int columnIndex)
               throws SQLException {
           return this.getStringArray(cs.getString(columnIndex));
        }
     
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i,
               String[] parameter, JdbcType jdbcType) throws SQLException {
           //由于BaseTypeHandler中已经把parameter为null的情况做了处理,所以这里我们就不用再判断parameter是否为空了,直接用就可以了
           StringBuffer result = new StringBuffer();
           for (String value : parameter)
               result.append(value).append(",");
           result.deleteCharAt(result.length()-1);
           ps.setString(i, result.toString());
        }
       
        
    }
    

    1.@MappedJdbcTypes定义是JdbcType类型,必须要是枚举类org.apache.ibatis.type.JdbcType所枚举的数据类型
    2.@MappedTypes定义的是JavaType的数据类型,描述哪些Java类型可被拦截。
    3.在我们启用了自定义的这个TypeHandler之后,数据的读写都会被这个类所过滤
    4.在setNonNullParameter方法中,重新定义要写往数据库的数据。
    5.在另外三个方法中我们将从数据库读出的数据类型进行转换。

  4. 注册 TypeHandler(SqlMapConfig.xml)

    <typeHandlers>
       <package name="com.neu.util"/>
    </typeHandlers>
    或
    <typeHandlers>
       <typeHandler handler="com.neu.util.StringArrayTypeHandler"/>
    </typeHandlers>
    
  5. 接口

    public interface MyUserMapper {
        MyUser getById(int id);
        
        int insert(MyUser user);
        
        int update(MyUser user);
    }
    
  6. mapper(可以不配置 typeHandler 属性,由mybatis自动选择)

    <?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.neu.mapper.MyUserMapper">
        <resultMap type="com.neu.po.MyUser" id="basicMap">
            <result column="interests" property="interests" typeHandler="com.neu.util.StringArrayTypeHandler" />
        </resultMap>
        <!-- 可以使用 resultMap 进行手工映射 -->
        <select id="getById" resultType="com.neu.po.MyUser">
            select * from myuser where id = #{id}
        </select>
        
        <insert id="insert">
            insert into myuser values(
                #{id},
                #{username,javaType=String,jdbcType=VARCHAR,typeHandler=org.apache.ibatis.type.StringTypeHandler},
                #{password},#{interests,typeHandler=com.neu.util.StringArrayTypeHandler}
            )
        </insert>
        
        <update id="update">
            update myuser set username = #{username},password= #{password},interests=#{interests}
            where id = #{id}
        </update>
    </mapper>
    
  7. 测试代码

    public class MyUserMapperTest {
        private SqlSession session;
        private MyUserMapper myuserMapper;
        
        @Before
        public void setup() throws IOException {
            //ctrl+2 L
            //读取配置文件
            InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
            //创建SqlSessionFactory
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //创建连接,相当于Connection
            session = sessionFactory.openSession();
            //返回DeptMapper接口的实现类
            myuserMapper = session.getMapper(MyUserMapper.class);
        }
        
        @After
        public void after() {
            //关闭会话
            session.close();
        }
    
        @Test
        public void testInsert() {
            int n = myuserMapper.insert(new MyUser(33,"tom","111",new String[]{"游泳","爬山"}));		
            
            System.out.println(n);
            
            session.commit();
        }
        
        @Test
        public void testGetById() {
            MyUser user = myuserMapper.getById(10);
            System.out.println(user);
        }
        
        @Test
        public void testUpdate() {
            int n = myuserMapper.update(new MyUser(33,"marry","222",new String[]{"游泳","爬山","钓鱼"}));		
            
            System.out.println(n);
            
            session.commit();
        }
    }
    

mybatis中 在 TypeHandlerRegistry 注册内置拦截器

public TypeHandlerRegistry(Configuration configuration) {
    this.unknownTypeHandler = new UnknownTypeHandler(configuration);

    register(Boolean.class, new BooleanTypeHandler());
    register(boolean.class, new BooleanTypeHandler());
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
    register(JdbcType.BIT, new BooleanTypeHandler());

    register(Byte.class, new ByteTypeHandler());
    register(byte.class, new ByteTypeHandler());
    register(JdbcType.TINYINT, new ByteTypeHandler());

    register(Short.class, new ShortTypeHandler());
    register(short.class, new ShortTypeHandler());
    register(JdbcType.SMALLINT, new ShortTypeHandler());

    register(Integer.class, new IntegerTypeHandler());
    register(int.class, new IntegerTypeHandler());
    register(JdbcType.INTEGER, new IntegerTypeHandler());

    register(Long.class, new LongTypeHandler());
    register(long.class, new LongTypeHandler());

    register(Float.class, new FloatTypeHandler());
    register(float.class, new FloatTypeHandler());
    register(JdbcType.FLOAT, new FloatTypeHandler());

    register(Double.class, new DoubleTypeHandler());
    register(double.class, new DoubleTypeHandler());
    register(JdbcType.DOUBLE, new DoubleTypeHandler());

    register(Reader.class, new ClobReaderTypeHandler());
    register(String.class, new StringTypeHandler());
    register(String.class, JdbcType.CHAR, new StringTypeHandler());
    register(String.class, JdbcType.CLOB, new ClobTypeHandler());
    register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
    register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler());
    register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
    register(JdbcType.CHAR, new StringTypeHandler());
    register(JdbcType.VARCHAR, new StringTypeHandler());
    register(JdbcType.CLOB, new ClobTypeHandler());
    register(JdbcType.LONGVARCHAR, new StringTypeHandler());
    register(JdbcType.NVARCHAR, new NStringTypeHandler());
    register(JdbcType.NCHAR, new NStringTypeHandler());
    register(JdbcType.NCLOB, new NClobTypeHandler());

    register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
    register(JdbcType.ARRAY, new ArrayTypeHandler());

    register(BigInteger.class, new BigIntegerTypeHandler());
    register(JdbcType.BIGINT, new LongTypeHandler());

    register(BigDecimal.class, new BigDecimalTypeHandler());
    register(JdbcType.REAL, new BigDecimalTypeHandler());
    register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
    register(JdbcType.NUMERIC, new BigDecimalTypeHandler());

    register(InputStream.class, new BlobInputStreamTypeHandler());
    register(Byte[].class, new ByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
    register(byte[].class, new ByteArrayTypeHandler());
    register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
    register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.BLOB, new BlobTypeHandler());

    register(Object.class, unknownTypeHandler);
    register(Object.class, JdbcType.OTHER, unknownTypeHandler);
    register(JdbcType.OTHER, unknownTypeHandler);

    register(Date.class, new DateTypeHandler());
    register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
    register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
    register(JdbcType.TIMESTAMP, new DateTypeHandler());
    register(JdbcType.DATE, new DateOnlyTypeHandler());
    register(JdbcType.TIME, new TimeOnlyTypeHandler());

    register(java.sql.Date.class, new SqlDateTypeHandler());
    register(java.sql.Time.class, new SqlTimeTypeHandler());
    register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());

    register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());

    register(Instant.class, new InstantTypeHandler());
    register(LocalDateTime.class, new LocalDateTimeTypeHandler());
    register(LocalDate.class, new LocalDateTypeHandler());
    register(LocalTime.class, new LocalTimeTypeHandler());
    register(OffsetDateTime.class, new OffsetDateTimeTypeHandler());
    register(OffsetTime.class, new OffsetTimeTypeHandler());
    register(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
    register(Month.class, new MonthTypeHandler());
    register(Year.class, new YearTypeHandler());
    register(YearMonth.class, new YearMonthTypeHandler());
    register(JapaneseDate.class, new JapaneseDateTypeHandler());

    // issue #273
    register(Character.class, new CharacterTypeHandler());
    register(char.class, new CharacterTypeHandler());
  }

mybatis 类型别名 注册:TypeAliasRegistry

说明:https://blog.csdn.net/lgl782519197/article/details/109066243
public TypeAliasRegistry() {
    registerAlias("string", String.class);

    registerAlias("byte", Byte.class);
    registerAlias("long", Long.class);
    registerAlias("short", Short.class);
    registerAlias("int", Integer.class);
    registerAlias("integer", Integer.class);
    registerAlias("double", Double.class);
    registerAlias("float", Float.class);
    registerAlias("boolean", Boolean.class);

    registerAlias("byte[]", Byte[].class);
    registerAlias("long[]", Long[].class);
    registerAlias("short[]", Short[].class);
    registerAlias("int[]", Integer[].class);
    registerAlias("integer[]", Integer[].class);
    registerAlias("double[]", Double[].class);
    registerAlias("float[]", Float[].class);
    registerAlias("boolean[]", Boolean[].class);

    registerAlias("_byte", byte.class);
    registerAlias("_long", long.class);
    registerAlias("_short", short.class);
    registerAlias("_int", int.class);
    registerAlias("_integer", int.class);
    registerAlias("_double", double.class);
    registerAlias("_float", float.class);
    registerAlias("_boolean", boolean.class);

    registerAlias("_byte[]", byte[].class);
    registerAlias("_long[]", long[].class);
    registerAlias("_short[]", short[].class);
    registerAlias("_int[]", int[].class);
    registerAlias("_integer[]", int[].class);
    registerAlias("_double[]", double[].class);
    registerAlias("_float[]", float[].class);
    registerAlias("_boolean[]", boolean[].class);

    registerAlias("date", Date.class);
    registerAlias("decimal", BigDecimal.class);
    registerAlias("bigdecimal", BigDecimal.class);
    registerAlias("biginteger", BigInteger.class);
    registerAlias("object", Object.class);

    registerAlias("date[]", Date[].class);
    registerAlias("decimal[]", BigDecimal[].class);
    registerAlias("bigdecimal[]", BigDecimal[].class);
    registerAlias("biginteger[]", BigInteger[].class);
    registerAlias("object[]", Object[].class);

    registerAlias("map", Map.class);
    registerAlias("hashmap", HashMap.class);
    registerAlias("list", List.class);
    registerAlias("arraylist", ArrayList.class);
    registerAlias("collection", Collection.class);
    registerAlias("iterator", Iterator.class);

    registerAlias("ResultSet", ResultSet.class);
  }

使用注解替代mapper文件

  1. 使用注解

    @Select("select * from dept")
    List<Dept> getAll();
    
    @Insert("insert into dept values(#{deptno},#{dname},#{loc})")
    int insert(Dept dept);
    
  2. 长 SQL 语句的写法

    @Select("select * from dept "+
            "where deptno = #{deptno}")
    Dept getById(int deptno);
    
    @Select({"select * from dept ",
             "where deptno = #{deptno}"})
    Dept getById(int deptno);
    
  3. ResultMap

    • 直接在接口方法上添加@Results注解

      //mybatis的版本号:3.5.4,支持@Results中的id属性
      @Select({"select * from dept ",
                  "where deptno = #{deptno}"})
          @Results(id="basicMap", value= {
                  @Result(column = "deptno",property = "deptno",id = true),
                  @Result(column = "dname",property = "dname"),
                  @Result(column = "loc",property = "loc"),
                  @Result(property = "emps",column = "deptno",many = @Many(select = "com.neu.mapper.EmpMapper.getByDeptno"))
          })
          Dept getById(int deptno);
          
          
      @Select("select * from emp where empno = #{empno}")
          @Results(value= {
                  @Result(
                          property = "dept",
                          column = "deptno",
                          one = @One(select = "com.neu.mapper.DeptMapper.getById"
                  ))
          })
          Emp getById(int empno);
      
    • 使用@ResultMap注解,引用@Results

      //basicMap可以是@Results的id或对应mapper.xml文件中<resultMap>的id属性
      @Select("select * from dept")
      @ResultMap("basicMap")
      List<Dept> getAll();
      
    1. 得到自增主键值

      @Insert("insert into dept values(null,#{dname},#{loc})")
          @SelectKey(
              statement = "select last_insert_id()",
              resultType = Integer.class,
              keyProperty = "deptno",
              before = false
          )
          int insert(Dept dept);
      

查询补充

//接口
List<Map<String,Object>> report();

//mapper
<select id="report" resultType="map">
        select ename,job,hiredate,dname,loc
        from emp e join dept d
        on e.deptno = d.deptno
</select>

MBG(Mybatis Generator)

  1. 定义:是一个Mybatis的代码生成器,是根据已经创建的数据库表生成实体类、mapper接口、sql映射文件

  2. 操作过程

    • 使用向导生成配置文件:generatorConfig.xml

    • 修改模板:

      • 改为使用“简单模板”

        <context id="context1" targetRuntime="Mybatis3Simple">
        
      • 使用默认模板

        <context id="context1" >
        
    • 修改配置

      <?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>
        <context id="context1" targetRuntime="Mybatis3Simple">
          <jdbcConnection connectionURL="jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=utf8" driverClass="com.mysql.jdbc.Driver" password="root" userId="root" />
          <javaModelGenerator targetPackage="com.neu.po" targetProject="mybatismbg" />
          <sqlMapGenerator targetPackage="com.neu.mapper" targetProject="mybatismbg"></sqlMapGenerator>
          <javaClientGenerator targetPackage="com.neu.mapper" targetProject="mybatismbg" type="XMLMAPPER" />
          
          <table schema="root" tableName="dept">
            <!-- <columnOverride column="???" property="???" /> -->
          </table>
          <table schema="root" tableName="emp">
            <!-- <columnOverride column="???" property="???" /> -->
          </table>
        </context>
      </generatorConfiguration>
      
    • 生成代码(配置文件右键)

    • 如果有实体关联,修改xml配置文件

      • 修改生成xml配置文件

        //generatorConfig.xml
        <table schema="root" tableName="emp">
            <columnOverride column="deptno" property="dept" javaType="com.neu.po.Dept" />
        </table>
        
      • 修改生成的mapper文件

        <!-- <result column="deptno" jdbcType="INTEGER" property="dept" /> -->
            
        <association property="dept" column="deptno" select="com.neu.mapper.DeptMapper.selectByPrimaryKey"></association>
        

        修改 dept =》 dept.deptno(注意:别修改列名)

    1. 使用Mybatis3模板

      • 生成的接口中有11个方法

        • 方法名中包含 primaryKey:根据主键进行相应的操作
        • 方法名中包含example:根据Example生成where语句来操作
        • 方法名中包含Selective:对部分列进行有选择操作(动态sql)
      • Example的作用:生成where语句

        @Test
            public void testGetByExample() throws IOException {
                EmpExample example = new EmpExample();
        //		example.or().andEnameEqualTo("SMITH").andSalGreaterThan(new BigDecimal(700));
        //		example.or().andEnameLike("%S%");
        //		example.or().andSalBetween(new BigDecimal(1500), new BigDecimal(2000));
        //		List<Integer> list = new ArrayList<>();
        //		list.add(7369);
        //		list.add(7499);
        //		
        //		example.or().andEmpnoIn(list);
                
                Dept dept = new Dept();
                dept.setDeptno(10);
                
                example.or().andDeptEqualTo(dept);
                
                List<Emp> list2 = empMapper.selectByExample(example);
                System.out.println(list2);
            }
            
        //修改EmpExample
        public Criteria andDeptEqualTo(Dept value) {
           addCriterion("deptno =", value.getDeptno(), "dept");
           return (Criteria) this;
        }
        

      练习:

      1. 生成Role和MyUser实体类、接口、mapper文件
      2. 根据角色Id查询该角色的所有用户信息

文章作者: FFFfrance
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 FFFfrance !