MyBatis笔记

MyBatis 笔记

MyBatis 是基于 Java 语言的开源的持久层框架,利用实体类和数据表之间产生了关联,通过映射文件中的 sql 语句对数据库进行操作

使用 maven 创建工程需要导入 mybatis 的依赖:

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

简单实例演示

mybatis的持久层开发有两种方式,一种是原始的 dao 开发,比较繁琐,还有一种是基于接口的 JDK 动态代理开发,也是最普遍的一种开发模式

原始dao开发模式

使用原始 dao 开发模式,首先第一步: 创建 mybatis 的核心配置文件,一般取名为 mybatis-config.xml

在dataSource标签中配置数据库连接,在mapper标签中配置xml映射文件目录,然后去书写xml映射文件

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///test"/>
                <property name="username" value="root"/>
                <property name="password" value="zhang"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/beanMapper.xml"/>
    </mappers>
</configuration>

第二步:在上面的映射文件目录对应的位置创建文件

mapper 标签的 namespace 属性自定义书写,select 标签的 id 不能与其他 id 重复,resultType 是和数据库表对应的实体类的全限定路径名,实体类仅仅只有和表中字段对应的属性及 get set toString 方法而已

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test1">
    <select id="findAll" resultType="club.hanzhe.bean.Bean">
        select * from test1
    </select>
</mapper>

第三步:创建dao类,通过dao接口类来操作 mapper 文件中的增删改查

dao类想要操作mapper文件需要使用工厂对象,工厂对象暂时就不在这里创建了,由调用者给他对象让他使用就行

操作mapper文件需要使用mapper文件的 namespace.标签id,例如 test1.findAll

public class BeanDao {
    private SqlSessionFactory factory ;
    public BeanDao( SqlSessionFactory factory ){
        this.factory = factory;
    }
    public List<Bean> findAll(){
        SqlSession sqlSession = factory.openSession();
        List<Bean> list = sqlSession.selectList("test1.findAll");
        return list;
    }
}

第四步:创建测试类,对写好的代码进行测试

因为调用一个dao都会使用一个工厂对象,所以这里就直接创建一个供所有dao使用,节省资源

public class AppTest {
    private static InputStream is = null;
    private static SqlSessionFactory factory = null;
    @Before
    public void before(){
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
        } catch (Exception e) {
            System.out.println("获取配置文件失败!");
        }
        factory = new SqlSessionFactoryBuilder().build(is);
    }
    @Test
    public void tes1(){
        BeanDao dao = new BeanDao(factory);
        List<Bean> list = dao.findAll();
        for (Bean bean : list)
            System.out.println(bean);
    }
}

基于接口的动态代理开发

使用动态代理开发模式,首先第一步: 创建 mybatis 的核心配置文件,一般取名为 mybatis-config.xml

这里和 dao 开发的配置文件一模一样,可以去上面 copy

第二步:在上面的映射文件目录对应的位置创建映射文件

这里和上面几乎一模一样,但是动态代理的 mapper 的 namespace 指向的必须是接口的全限定名称

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="club.hanzhe.dao.BeanDao">
    <select id="findAll" resultType="club.hanzhe.bean.Bean">
        select * from test1
    </select>
</mapper>

第三步:按照上面映射文件目录创建接口

这里和上面不同的是不需要太多繁琐的结构,只需要创建一个方法即可对应mapper中的增删改查,但是需要注意一点:接口方法名必须和mapper的CRUD标签id一致,否则会报错

public interface BeanDao {
    List<Bean> findAll();
}

第四步:创建测试类,对写好的代码进行测试

public class TestDemo {
    private SqlSessionFactory factory = null;
    @Before
    public void before(){
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
        }catch (Exception e){
            System.out.println("加载核心配置文件失败");
            System.exit(0);
        }
        this.factory = new SqlSessionFactoryBuilder().build(is);
    }
    @Test
    public void test1(){
        SqlSession session = factory.openSession();
        BeanDao mapper = session.getMapper(BeanDao.class);
        List<Bean> list = mapper.findAll();
        for (Bean bean : list)
            System.out.println(bean);
    }
}

注意:在 openSession 的时候是可以传入一个 boolean 参数的,如果不传参数默认为 false,如果要执行 DML 语句进行增删改的话,一定要传入 true 做为参数,否则他不会自动提交 ( 你可以手动提交 ),查询无需提交所以不需要设置

Mybatis 的核心配置文件

mybatis 的核心配置文件,一般都起名为 mybatis-config.xml 或者是 sqlMapConfig.xml ,在核心配置文件中可以通过某些标签对 mybatis 进行一些配置

注意:mybatis 的核心配置文件内不可以书写中文注释 (英文或数字可以),否则报错

mybatis 提供了很多标签进行配置,但是这些标签也有着先后顺序,如果标签不按顺序书写也是会报错的

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

上面来自 mybatis 官方文档,这里会挑常用的标签进行笔记

Environments 环境配置

1. 环境的选择

在 mybatis 配置文件中使用 environments 标签配置环境,在他下面可以有一个或多个 environment 子标签,每个都代表一个环境,然后在 environments 标签中使用 default 属性对环境进行选择

这里使用 default 对环境进行选择,目前选择的是MySQL的环境

<environments default="mysql">
    <environment id="mysql">
        这是MySQL的环境
    </environment>
    <environment id="oracle">
        这是oracle的环境
    </environment>
</environments>

除开配置文件内的默认环境,也可以在打开打开会话工厂的时候传入指定环境的id进行选择环境

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is, "mysql");

注意: 尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

2. 事务管理器

在每个 environment 子标签环境中有 transactionManager 标签的 type 属性可以对 SQL 进行事务控制管理,管理事务的管理器有两种:【 JDBC 】【 MANAGED 】

事务管理器说明
JDBC直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED什么都不做,让容器来管理事务的整个生命周期,不建议使用

建议使用 JDBC 来管理事务

<environment id="mysql">
    <transactionManager type="JDBC"/>
</environment>
3. 数据源

数据源是配置 mybatis 和数据库进行连接的相关配置,他由 environment 标签下的 dataSource 标签进行设置

通过 dataSource 标签的 type 属性可以选择数据源类型:

类型说明
UNPOOLED只是每次被请求时打开和关闭连接,反应较慢,适用于简单小型项目
POOLED相对于UNPOOLED相比使用了 数据库连接池 的感念
JNDI能在如 EJB 或应用服务器这类容器中使用

数据源最基本的四个属性:

  • 【driver】 数据库连接驱动类
  • 【url】 数据库链接地址
  • 【username】 用户名
  • 【password】 密码

最常见的 environments 标签配置

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql:///test"/>
            <property name="username" value="root"/>
            <property name="password" value="******"/>
        </dataSource>
    </environment>
</environments>

Mappers 映射标签

书写的 mapper 文件需要被映射到核心配置文件中,映射的标签就是 mappers ,他下面有两个子标签,分别是 mapperpackage 映射方法如下:

1. 映射的文件在resources目录下

<mappers>
    <!-- 映射单个文件 -->
    <mapper resource="beanMapper.xml"/>>
    <!-- 使用 * 通配符映射多个文件 -->
    <mapper resource="*Mapper.xml"/>
</mappers>

2. 映射的文件在dao包下

当 mapper 文件在 dao 包下的时,mapper 和接口必须是同名的,或者在 resources 目录下有着同级的目录

<mappers>
    <!-- 映射单个文件 -->
    <mapper class="club.hanzhe.dao.BeanDao" />
    <!-- 映射多个文件 -->
    <package name="club.hanzhe.dao"/>
</mappers>

3. 接口注解开发

<mappers>
    <package name="club.hanzhe.dao"/>
</mappers>

注意!当mapper文件在dao包下的时候,需要在maven的pom文件中添加如下代码,否则xml文件可能不会被打包发布

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

Properties 属性

我们在使用传统 JDBC 的时候都会把 driver,url 等等放在一个 propertis 后缀的文件中,这样可以降低代码的耦合性,方便环境切换,mybatis 中也支持这种做法,使用 properties 标签就可以实现

1. 手写 properties 配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1/库名
username=root
password=*****

2. 使用 properties 标签将配置文件引入进来

<!-- 使用该标签将配置文件引入进来,然后就可以使用 ${} 符号来调用配置文件内的值了 -->
<properties resource="db.properties" />
<!-- 例如: -->
<property name="driver" value="${driver}">

TypeAliases 别名

在我们的 mapper 映射文件中,CRUD 标签中的参数,返回结果 resultType 通常都是全限定名,例如:

<select id="findAll" resultType="club.hanzhe.bean.Bean"></select>

这个时候我们就可以使用 typeAliases 标签下的 typeAlias 子标签配置类别名,可以简化全限定名书写格式

abc就是这个类的类别名,就可以在映射文件中使用了

<typeAliases>
    <typeAlias type="club.hanzhe.bean.Bean" alias="abc" />
</typeAliases>

<select id="findAll" resultType="abc"></select>

typeAlias 标签中的 alias 属性也可以忽略不写,默认已类名作为别名 (别名首字母小写即可)

<typeAliases>
    <typeAlias type="club.hanzhe.bean.Bean" />
</typeAliases>

<select id="findAll" resultType="bean"></select>

但如果是个较大的项目,表和实体类比较多,如果逐个实体类配置的话会很麻烦,这时可以使用 package 子标签

将指定包下的所有类全部配置别名,别名为类本身名字 (首字母小写)

<typeAliases>
    <package name="club.hanzhe.bean" />
</typeAliases>

<select id="findAll" resultType="bean"></select>

Settings 全局设置

在 mybatis 中可以对全局进行一些设置,设置需要用 settings 下的 setting 子标签实现,格式体现为:

<settings>
  <setting name="设置名称" value="对应参数值"/>
</settings>

常用的设置有:

设置名作用描述参数
cacheEnabled设置全局缓存的开启和关闭boolean
defaultStatementTimeout设置超时时间,它决定驱动等待数据库响应的秒数。任意正整数
mapUnderscoreToCamelCase是否开启驼峰命名规则boolean
logImpl配置日志信息,个人推荐使用 STDOUT_LOGGING 日志@官方文档

Mapper 映射文件

mapper 映射文件,用来负责和数据库交互的 sql 代码,主要是增删改查四个标签为主:

增删改标签

增删改标签是用来书写插入 sql 的标签,比较常用的几个属性如下:

<insert
	id="addBean"
	parameterType="club.hanzhe.bean"
	flushCache="true"
	timeout="20">
属性作用
id用来作为标签的标识符,使用id可以直接找到当前标签调用
parameterType接受的参数的类型,如果参数类型是集合,那么就填集合内元素的类型
flushCache增删改标签默认设置为true,只要语句被调用,就会清空本地和二级缓存
timeout抛出异常之前,驱动程序等待响应的时间,默认为空值

查询标签

select 标签是用来专门书写查询语句的标签,比较常用的几个属性如下:

<select
    id="selectPerson"
    parameterType="int"
    resultType="hashmap"
    resultMap="personResultMap"
    flushCache="false"
    useCache="true"
    timeout="10"
    fetchSize="256"
    statementType="PREPARED"
    resultSetType="FORWARD_ONLY">

除开增删改相同的属性之外,查询有着自己的属性

属性作用
resultType用来设置查询返回的数据对应的实体类
resultMap属于高级的parameterType,他可以手动配置实体类属性和数据库字段的映射
useCacheselect 默认为 true,执行查询后将查询结果缓存在二级缓存中

添加时返回 ID

这里记一个十分好用的小功能,当我们执行 insert 之后,想要立刻操作这行记录,但是他的主键是自增的,我们想要操作他需要获取他的 ID,这个时候我们可以通过属性设置回显 ID

假设当前有一个 bean,属性为 userid,username,password

<!-- useGeneratedKeys="true" 取出数据库内自动生成的主键 -->
<!-- keyProperty="userid" 将主键设置在 bean 中的某个属性上 -->
<insert id="addUser" parameterType="user" useGeneratedKeys="true"keyProperty="userid">
	insert into t_user values(#{username}, #{password})
</insert>
@Test
public void test(){
    User user = new User();
    user.setUsername("张");
    user.setPassword("123");
    userDao.addUser(user);
    // 当我们执行插入语句后,如果正常运行,那么userid就会成功赋值
    System.out.println(user.getUserid());
}

SQL 代码片段

可以被用来定义可重用的 SQL 代码段,例如:

定义了 id 为 t_user 的 sql 代码片段,在下面的增删改查中就可以使用 include 来调用了

<sql id="t_user">userid, username, usersex, usertel</sql>

<select id="selectAll" resultType="user">
    SELECT <include refid="t_user" /> FROM t_user
</select>

${ } 和 #{ } 的区别

${ }和#{ }他们都是用来接收传入参数的,只不过有些细节需要留意,假设现在有一行SQL语句:

select * from t_user where userid = 1;

其中作为查询条件的 1 是需要接收传入参数的,那么获取到传入参数有两种方法:

  • ${ },拼接SQL字符串
  • #{ },作为SQL占位符

如果使用 ${} 的话,通过日志可以看到,它以拼接字符串的方式执行,这样的话就很容易收到SQL注入的攻击

select * from t_user where userid = 1;

但是如果使用 #{} 的话,他是将 SQL 代码预处理之后在执行之前进行参数替换,传入的参数都将作为普通参数对待,通过执行日志就可以看到:

select * from t_user where userid = ? ;

这是二者最明显的差距,通过占位符可以有效防止SQL注入攻击,推荐使用#{ }

ResultMap 标签

一般使用 resultType 返回对象的时候,是数据库自动检测实体类中和字段匹配的属性进行封装,但是如果实体类中的属性和表中的字段截然不同的话,就需要手动配置他们之间的映射关系了

<!-- 
  id:为当前标签的命名,会在select标签中的返回类型中用到
  type:为返回的主类的类型,Student中包含Score类型的变量,所以Sutdent是主类
  extends:继承,将指定的resultMap的id作为值放在这里,会继承之前书写的映射
  autoMapper:为其他属性自动匹配的开关,默认为false关闭状态
   为false时,只有手动配置的映射会匹配成功,未设置的为null值
   为true时,将按照手动配置的进行匹配,没有手动配置的会自动按照变量名匹配
-->
<resultMap id="map1" type="club.hanzhe.pojo.U_T">
    <!--
       id标签为设置当前主类与数据表中对应表的主键的匹配
       column:数据表中的字段
       property:与该字段对应的本类中的属性
     -->
    <id column="rowNo" property="rowNo" />
    <!--
   result标签为设置当前主类与数据表中对应表的其他字段的匹配
   column:数据表中的字段
   property:与该字段对应的本类中的属性
  -->
    <result column="u_id" property="userid" />
    <!--
   association标签为设置当前主类中映射的其他类
   property:类中的属性
   javaType:属性所对应的那个类的全限定名,可以使用别名
   autoMapping:自动匹配表中的其他字段和类中的属性
  -->
    <association property="tel" javaType="club.hanzhe.pojo.Tel">
        <id column="t_id" property="telid" />
    </association>
    <!--
   collection用来映射集合,多用于一对多查询 
   与association的唯一差别就是javaType变成了ofType 
  -->
    <collection property="tel" ofType="club.hanzhe.pojo.Tel">
        <id column="t_id" property="telid" />
    </collection>
</resultMap>

动态 SQL

通过传入的参数对 sql 进行灵活化使用,类似 Java 一样,通过 判断循环 来控制 SQL 的最终执行

if 判断标签

如果接收的username参数不为空的话,就追加当前标签内的sql语句

<select id="findBean" resultType="bean">
    select * from test
    <if test="id != null and id != ''">
        where id = #{id}
    </if>
</select>

where 过滤标签

使用 where 标签之后,如果 where 内有符合 if 条件的会自动添加 where 关键字,如果没有符合的就不添加

如果有多个 if 符合条件,需要在前面加上 and 或者 or 等判断条件,如果是第一个成立的条件会默认省略前面的 and 或 or,后续的会添加

<select id="findUser" resultType="user">
    select * from t_user
    <where>
        <if test="userid != null">
            and userid = #{userid }
        </if>
        <if test="username != null">
            and username like #{username }
        </if>
        <if test="usersex != null">
            and usersex = #{usersex }
        </if>
        <if test="usertel!= null">
            and usertel = #{usertel }
        </if>
    </where>
</select>

choose 标签

choose 标签有着和 switch 类似的功能,他要求当前判断至少成立一个才可以结束,如果没有成立的会执行otherwise

<choose>
    <when test=""></when>
    <when test=""></when>
    <otherwise></otherwise>
</choose>

set 标签

使用 set 标签之后,如果 set 内有符合 if 条件的会自动添加 set 关键字,如果没有符合的就不添加,需要注意一点的是,set → if 内的 sql 结尾一定要带上逗号,系统会自动省略但不会自动追加。

<update id="updateUser" parameterType="user" >
    update t_user
    <set>
        <if test="username != null and username != ''">
            username = #{username },
        </if>
        <if test="usersex != null and usersex != ''">
            usersex = #{usersex },
        </if>
        <if test="usertel != null and usertel != ''">
            usertel = #{usertel },
        </if>
    </set>
    where userid = #{userid }
</update>

foreach 标签

foreach 标签用来遍历传进来的集合或数组容器,多用于批量删除操作,里面的属性解释如下:

<delete id="find1">
	delete from bean where id in
	<foreach collection="list" open="(" close=")" separator=", " item="i">
		#{ i }
	</foreach>
</delete>
  • collection:传进来被遍历的那个容器的名字,可以是数组或集合
  • open:循环开始前需要添加的前缀
  • close:循环结束后需要添加的后置
  • separator:每循环一次时需要在中间添加的分隔符
  • item:被循环出来的每个字段,在标签内直接使用即可

cache 缓存标签

一级缓存

在 mybatis 中一级缓存是默认开启的,在进行 openSession 的时候就自动打开了一级缓存,且对于一级缓存的操作,只能清空,不能禁用,一级缓存的作用范围是当前的 SqlSession 实例

在同一个 SqlSession 实例中,两次同样的查询返回的结果是一致的,但是如果是两个SqlSession那么进行相同的查询结果就会不同,这里就不写了

public void test4(){
    SqlSession session = this.factory.openSession(true);
    BeanDao mapper = session.getMapper(BeanDao.class);
    Bean bean1 = mapper.findById(7844);
    Bean bean2 = mapper.findById(7844);
    System.out.println(bean1 == bean2);
}
二级缓存

二级缓存的范围是基于当前的 mapper.xml 配置文件的 mapper 标签,也就是当前的 namespace 下,一个二级缓存可以横跨多个一级缓存,而二级缓存默认是关闭的,开启二级缓存的方法就是使用 cache标签

没错,只要在 mapper 下面加上这么一句代码,二级缓存就开启完成了,简单粗暴

<cache />

在开启二级缓存后还不能立刻使用,会报错,需要让该 mapper 相关的所有 bean 实现 Serializable 序列化接口

Mybatis 注解开发

CRUD 注解

在 mybatis 中也可以不使用 mapper 映射文件,改为使用注解开发,分别相对着增删改查四个注解

@Insert("insert into t_user values(null,#{name},#{sex},#{address})")
public int saveUser(User user);

@Delete("DELETE FROM t_user WHERE u_id = #{abc}")
public int removeUser(Integer id);

@Update("update t_user set u_address=#{address} where u_name = #{name}")
public int updateUser(User user);

@Select("select * from t_user where u_id = #{abc}")
public User findUserById( Integer id );

注意!使用 mapper 文件的时候需要扫描 mapper 文件所在位置,然后才可以使用,使用注解开发也需要扫描:

将所有带有注解的接口都扫描

<mappers>
    <package name="club.hanzhe.dao"/>
</mappers>

Result 注解

使用 xml 开发时,会遇到字段与实体类属性名不匹配造成封装失败的情况,起别名解决是一种方法,但是一般都使用 resultMap 结果映射,将字段与属性匹配,注解开发也可以使用 resultMap,对应的注解是 @Results

使用注解的方式匹配字段与属性查询

@Results(
    id = "r1",	// id:给当前results起名字,像resultMap一样继承使用
    value = {	// value:配置多个映射
		/*
		 *  @Result中的属性:
		 *  	id:表中的id列是否为主键,是为true,不写默认为false
		 *  	column:表中的字段
		 *  	property:表中字段对应的pojo中的属性
		 *  	只需要将不匹配的字段属性配上即可,匹配的可以省略不写
		 */
        @Result( column = "u_id" , property = "id" ),
        @Result( column = "u_name" , property = "name" ),
        @Result( column = "u_sex" , property = "sex" ),
        @Result( column = "u_address" , property = "address" )
    }
)
public User findUserById( Integer id );

如果有另一个查询与他的规则相同,那么可以引用之前写的Results的id属性

@Select("select * from t_user where u_name = #{abc}")
@ResultMap("r1")
public User findUserByName( String name );

扩展功能

Mybatis 逆向工程

逆向工程是根据数据库中表的信息进行自动创建实体类,接口,映射文件的技术

1. 环境配置

使用逆向工程必须引入他的依赖或jar包

<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.3.5</version>
</dependency>
2. 逆向工程配置文件

你可以在任意位置 ( 包括项目外 ) 创建逆向工程所需要的配置文件,需要手动配置的地方有以下几点:

  • properties 标签中的配置文件需要自己书写,也可以书写该标签及文件
  • jdbcConnection 标签需要修改,修改需参考上面的 properties 配置文件
  • javaModelGenerator 标签需要修改,他是实体类生成的目标包路径
  • sqlMapGenerator 标签需要修改,他是 mapper 映射文件生成的目标路径
  • javaClientGenerator 标签需要修改,他是接口生成的目标包路径
  • table 标签的 tableName 属性需要修改,他是逆向工程所参考的数据表
    • 如有多个表被参考就书写多个 table 标签,可以直接复制修改 tableName 属性
<?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>
    <properties resource="db.properties"></properties>
    <context id="testTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!--是否去除自动生成的注释 true是:false 否-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--数据库连接-->
        <jdbcConnection driverClass="${driver}" connectionURL="${url}" userId="${username}" password="${password}"></jdbcConnection>
        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL和NUMERIC类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!--生成的实体类存放的位置-->
        <javaModelGenerator targetProject="src/main/java" targetPackage="club.hanzhe.bean">
            <!--enableSubPackages,是否让schema作为包的后缀-->
            <property name="enableSubPackages" value="false"/>
            <!--从数据库返回的值被清除前后空格-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!--mapper映射文件存放的位置-->
        <sqlMapGenerator targetProject="src/main/resources" targetPackage="mappers">
            <property name="enableSubPackages" value="false"></property>
        </sqlMapGenerator>
        <!--targetPackage:mapper接口生成的位置-->
        <javaClientGenerator type="XMLMAPPER" targetProject="src/main/java" targetPackage="club.hanzhe.dao">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
        <!--tableName为逆向工程针对的表的表名,可以通配符匹配所有表,剩下的属性统统false-->
        <table tableName="%"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false"></table>
    </context>
</generatorConfiguration>
3. 使用逆向工程

在环境配置完成后使用下面这段模板代码,运行后就会将实体类,接口,mapper文件自动生成

需要在改代码中手动设置配置文件的文件名及位置

import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Generator {
    @Test
    public void create(){
        try {
            List<String> warnings = new ArrayList();
            boolean overWriter = true;
            // 这里加载刚刚创建的逆向工程配置文件
            File configFile = new File("文件位于磁盘的绝对路径");
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config = cp.parseConfiguration(configFile);
            DefaultShellCallback callback = new DefaultShellCallback(overWriter);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            myBatisGenerator.generate(null);
        }catch (Exception e){
            System.out.println("操作失败!");
            System.out.println("==================================================");
            System.out.println(e);
            e.printStackTrace();
        }
    }
}

PageHelper 分页插件

pageHelper 插件是针对 mybatis 设计的一款分页插件,通过拦截器对 sql 进行操作,使其拥有分页的能力

1. 环境配置

使用 pageHelper 分页插件需要导入他的 maven 依赖或者导入他的 jar 包

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <!-- 可以官网查询最新版 -->
    <version>5.0.0</version>
</dependency>

在 maven 依赖添加完成后,还需要在 mybatis 的核心配置文件中使用 plugins 标签注册 pageHelper 插件

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
2. 使用PageHelper

PageHelper 依赖引入后,在程序中就有了 PageHelper 类,调用它的 startPage 静态方法,后紧跟的第一条查询语句就是分页查询

startPage 的静态方法需要两个参数,第一个是查询的页码,第二个是每页的查询数量

public void test1(){
    // 查询第二页,每页5条记录
    PageHelper.startPage(2, 5);
    List<Bean> list = mapper.findAll();
    for (Bean bean : list)
        System.out.println(bean);
    System.out.println(list);
}

分页除了 PageHelper 类,还有一个 PageInfo 可以使用,将查询的结果封装到 PageInfo 中,可以查询一些和分页相关的信息

public void test1(){
    SqlSession session = factory.openSession();
    BeanDao mapper = session.getMapper(BeanDao.class);
    PageHelper.startPage(2, 5, true);
    PageInfo info = new PageInfo(mapper.findAll());
    System.out.println("总页码:" + info.getPages());
    System.out.println("总记录数:" + info.getTotal());
    System.out.println("结果集:");
    List<Bean> list = info.getList();
    for (Bean bean : list)
        System.out.println(bean);
}
3. PageInfo常用参数

在将结果集封装到 PageInfo 中的时候,可以可选性的传入一个导航页码的参数,可以获取到和当前页相邻的页码

public void test1(){
    SqlSession session = factory.openSession();
    BeanDao mapper = session.getMapper(BeanDao.class);
    PageHelper.startPage(201, 5, true);
    // 在创建info对象的时候可以跟随一个int类型,这个值是当前页附近的页码的数量
    PageInfo info = new PageInfo(mapper.findAll(), 7);
    System.out.println("当前页:" + info.getPageNum());
    System.out.println("每页显示数量:" + info.getPageSize());
    System.out.println("当前页信息:");
    for (Object obj : info.getList())
        System.out.println(obj);
    System.out.println("总页码:" + info.getPages());
    System.out.println("总记录数:" + info.getTotal());
    System.out.println("上一页:" + info.getPrePage());
    System.out.println("下一页:" + info.getNextPage());
    System.out.println("是否首页:" + info.isIsFirstPage());
    System.out.println("是否尾页:" + info.isIsLastPage());
    System.out.println("导航条页码:");
    for (int page : info.getNavigatepageNums() )
        System.out.print( page + "  " );
    System.out.println("\n导航条中首页" + info.getNavigateFirstPage());
    System.out.println("导航条中尾页" + info.getNavigateLastPage());
}
  • 这里需要注意!每页显示数量是指分页是设置的数量,例如设置每页只显示5条,获取到的就是5,而不是最后一页只显示三条就返回三,这是错误的
合理化查询

在网页中往往有些人会钻空子乱改数据,例如只有20页数据,他修改了参数请求到了第50页,这种情况经常会发生,所以在注册 pageHelper 的时候可以添加一个参数使数据变得合理化

<plugin interceptor="com.github.pagehelper.PageInterceptor">
    <property name="reasonable" value="true" />
</plugin>

Lombok 插件

在我们进行查询的时候,需要将查询的结果封装到指定的实体类中,而对应的实例类需要书写响应的 get set 方法,构造方法及 toString 方法,这样比较麻烦,这是可以使用 lombok 插件进行自动生成功能

1. 环境配置

使用 lombok 需要引入他的 maven 依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
</dependency>

在依赖引入后还需要在编辑器中安装 lombok 的插件 ( IDEA 编辑器为例 ) File → settings → plugins → install JetBrains plugin... 在里面搜索 lombok 下载安装,而后在 file → settings → build,Exe.. → Compiler → Annotation Pro... 里面选中当前项目,在右面的 Enable annotation processing 选项打勾

2. 使用 Lombok 插件

在目标实体类上,只需要书写好属性即可,无需书写其他多余方法,使用 lombok 提供的注解用来一键生成:

注解作用
@Getter一键生成所有 get 方法
@Setter一键生成所有 set 方法
@ToString一键生成 toString 方法
@Data一键生成 get set toString 等方法
@NoArgsConstructor生成无参构造方法
@AllArgsConstructor生成有参构造方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值