MyBatis的高级特性
1 学习目标
1,理解Mybatis多对多关系
2,掌握Mybatis的延迟加载
3,掌握Mybatis缓存
4,掌握逆向工程生成mapper和实体类
2 Mybatis 延迟加载
2.1 延迟加载介绍
通过前面的学习,我们已经掌握了 Mybatis 中一对一,一对多,多对多关系的配置及实现,可以实现对象的关联查询。实际开发过程中有时候我们并不需要在加载用户信息时,就加载他的账户信息。 而是在使用用户账号的时候,再向数据库查询,此时就是我们所说的延迟加载。
即时加载:
// 条件查询
@Test
public void findAll() throws Exception {
// SELECT u.*,a.* FROM USER u LEFT JOIN account a ON a.UID=u.id;
// 执行userDao.findAll()方法,执行查询用户、账户信息,一次加载所有的数据,这种叫做及时加载。
List<User> list = userDao.findAll();
for(User u : list){
System.out.println(u);
System.out.println(u.getAccounts());
}
}
2.2 何为延迟加载?
延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
好处: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
如何实现延迟加载:前面实现多表操作时,我们使用了resultMap 来实现一对一,一对多,多对多关系的操作。主要是通过 association、 collection 实现一对一及一对多映射。 association、 collection 具备延迟加载功能。
思考:什么是及时加载?什么是延时加载?
及时加载:一次加载所有数据。
延迟加载:也叫做懒加载,再需要用到数据时候再查询数据。
2.3 一对一实现延时加载
2.3.1 实现需求
需求:查询Account账户信息时候,也要显示User用户信息,但User用户信息用到的时候再向数据库发送查询语句。
数据库中实现:
-- 一对一延迟加载
-- 需求:查询账户,同时也要显示用户。但用户信息是再用到的时候再查询.
-- 实现过程:
-- 1) 查询账户
SELECT * FROM account
-- 3) 使用用户对象数据时候,查询用户
SELECT * FROM USER WHERE id=46
2.3.2 entity
public class Account {
private int accountId;
private int uid;
private double money;
// 一个账户对应一个用户
private User user;
}
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
// 一个用户,对应多个账户
private List<Account> accounts;
}
2.3.3 dao
public interface AccountMapper {
/**
* 查询账户
*/
List<Account> findAll();
}
public interface UserMapper {
/**
* 根据用户id查询
*/
User findById(int id);
}
2.3.4 UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itdfbz.dao.UserMapper" >
<select id="findById" resultType="user">
select * from user where id=#{id}
</select>
</mapper>
2.3.5 AccountMapper.xml 延时加载关键配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itdfbz.dao.AccountMapper">
<resultMap id="accountResultMap" type="account">
<!--1. 账户信息映射-->
<id property="accountId" column="accountId"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--2. 延时加载的方式,查询账户的用户-->
<!--select 延时加载的语句id(名称空间.方法)-->
<!--column="uid" 表外键字段-->
<association property="user" javaType="user" column="uid"
select="com.itdfbz.dao.UserMapper.findById"></association>
</resultMap>
<select id="findAll" resultMap="accountResultMap">
SELECT * FROM account
</select>
</mapper>
2.3.6 测试,观察问题
@Test
public void test1() {
AccountMapper accountMapper = session.getMapper(AccountMapper.class);
List<Account> accountList = accountMapper.findAll();
for (Account account : accountList) {
System.out.println(account.getAccountId());
}
}
执行结果:
发现,我们在测试中,只输出了账户信息,并没有使用用户信息,但还是查询了用户,并没有应用懒加载。如何解决?
2.3.7 解决方案
2.3.7.1 解决1:
查看mybatis官网
http://www.mybatis.org/mybatis-3/zh/configuration.html
- 1
打开页面,找到settings
然后在SqlMapConfig.xml中配置开启懒加载支持
最后,再次执行测试
1.测试类中没有使用Account账户的User信息
@Test
public void find() throws Exception{
List<Account> list = accountDao.findAccounts();
for (Account a : list) {
System.out.println(a.getAccountId() + ","+a.getUid() + "," +a.getMoney());
}
}
测试结果
2.测试类中有使用Account账户的User信息
@Test
public void test1() {
AccountMapper accountMapper = session.getMapper(AccountMapper.class);
List<Account> accountList = accountMapper.findAll();
for (Account account : accountList) {
System.out.println(account.getAccountId()+"----"+account.getUser());
}
}
测试结果: 可以看到使用对象数据的时候,才向数据库发送查询的SQL
2.3.7.2 解决2:
(1) 注释SqlMapConfig.xml中全局懒加载的的开启
(2) 修改映射文件
通过打印的SQL可以看到,懒加载一样生效:
2.3.8 小结
通过本示例,我们可以发现 Mybatis 的延迟加载对于提升软件性能这是一个不错的手段。实现的关键: association 的配置
<resultMap id="accountResultMap" type="account">
<!--1. 账户信息映射-->
<id property="accountId" column="accountId"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--2. 延时加载的方式,查询账户的用户-->
<!--select 延时加载的语句id(名称空间.方法)-->
<!--column="uid" 表外键字段(要传入findById方法的参数)-->
<!--
fetchType:懒加载设置
lazy:开启懒加载
eager:立即加载
-->
<association property="user" javaType="user" column="uid" fetchType="lazy"
select="com.itdfbz.dao.UserMapper.findById"></association>
</resultMap>
2.4 一对多实现延时加载
2.4.1 需求
查询用户信息,再使用用户账户时候再查询账户。
数据库实现:
-- 一对多延迟加载
-- 1) 查询用户
SELECT * FROM USER;
-- 2) 使用用户的账户对象数据时候再查询账户
SELECT * FROM account WHERE uid=46;
2.4.2 entity
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 一个用户,对应多个账户
private List<Account> accounts;
}
2.4.3 dao
public interface UserMapper {
/**
* 查询所有用户
*/
List<User> findAll();
}
public interface AccountMapper {
/**
* 根据用户的id查询
*/
List<Account> findAccountByUserId(Integer userId);
}
2.4.4 AccountMapper.xml
<!--根据用户,查询其下的多个账户-->
<select id="findAccountByUserId" resultType="account">
select * from account where uid=#{userId}
</select>
2.4.5 UserMapper.xml 延时加载关键配置
<resultMap id="userResultMap" type="user">
<id property="id" column="id"></id>
<result column="username" property="username"></result>
<result column="sex" property="sex"></result>
<result column="address" property="address"></result>
<!--
collection:一对多映射
property:JavaBean中的实体类的多方属性名
column: 本表的id(要传入findAccountByUserId的参数)
ofType:属性类型
select:映射的方法
-->
<collection property="accounts" column="id"
ofType="account"
select="com.itdfbz.dao.AccountMapper.findAccountByUserId">
</collection>
</resultMap>
<select id="findAll" resultMap="userResultMap">
select * from user
</select>
2.4.6 开启延时加载支持
2.4.7 测试
@Test
public void test1() {
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> userList = userMapper.findAll();
for (User user : userList) {
System.out.println(user.getSex());
}
}
测试结果:
// 查询用户
@Test
public void find() throws Exception{
List<User> list = userDao.findUsers();
for (User u : list) {
System.out.println(u.getId() + "," + u.getUsername());
System.out.println(u.getAccounts());
}
}
2.5. 注解实现延迟加载开发
2.5.1 注解实现一对一映射及延迟加载
2.5.1.1 entity
(1) 账户与用户,一对一
public class Account implements Serializable {
private int accountId;
private int uid;
private double money;
//一个账号对应一个账户
private User user;
}
(2) 用户与账户,一对多
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//一个用户对应多个账号
private List<Account> accountList;
}
2.5.1.2 dao
public interface UserMapper {
// 根据用户id查询
@Select("select * from user where id=#{id}")
User findById(int id);
}
package com.itdfbz.dao;
import com.itdfbz.entity.Account;
import com.itdfbz.entity.User;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
public interface AccountMapper {
/*
*
* @One:代表一对一
* select:要映射到本表属性的数据提供方法
* user:本类中要映射的属性名
* uid:外键,要传入findById方法的参数
* fetchType: 配置懒加载
* LAZY:懒加载
* EAGER:立即加载
*
* */
@Select("select * from account where accountId=#{id}")
@Results({
@Result(id=true,property = "accountId",column = "accountId"),
@Result(property = "uid",column = "uid"),
@Result(property = "money",column = "money"),
@Result(property = "user",column = "uid",javaType = User.class,
one = @One(select = "com.itdfbz.dao.UserMapper.findById",fetchType = FetchType.EAGER )
)
})
Account findById(Integer id);
}
2.5.1.3 测试
@Test
public void test1(){
AccountMapper mapper = session.getMapper(AccountMapper.class);
Account account = mapper.findById(1);
System.out.println(account.getAccountId());
System.out.println(account.getUser());
}
2.5.2 注解实现一对多映射及延迟加载
2.5.1.1 dao 接口
/**
* many:代表一对多
* accountList:代表本类中的多方属性名
* id:要传入findByUserId的参数
* List.class:多方集合类型
* FetchType.LAZY:懒加载
*
*/
@Select("select * from user where id=#{id}")
@Results({
@Result(id = true,property = "id",column = "id"),
@Result(property = "username",column = "username"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "sex",column = "sex"),
@Result(property = "address",column = "address"),
@Result(property = "accountList",column = "id",javaType = List.class,
many=@Many(select = "com.itdfbz.dao.AccountMapper.findByUserId",fetchType = FetchType.LAZY)
)
})
2.5.1.2 测试
@Test
public void test2() {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.findById(46);
System.out.println(user.getUsername());
List<Account> accountList = user.getAccountList();
for (Account account : accountList) {
System.out.println(account);
}
}
3 Mybatis 缓存机制
3.1 缓存介绍
像大多数的持久化框架一样, Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。Mybatis 中缓存分为一级缓存,二级缓存。
从图中可以看出什么 ? 一级缓存是基于SqlSessoion的缓存,一级缓存的内容不能跨sqlsession。由mybatis自动维护。二级缓存是基于映射文件的缓存,缓存范围比一级缓存更大。不同的sqlsession可以访问二级缓存的内容。哪些数据放入二级缓存需要自己指定。
3.2 一级缓存测试
同一个SqlSession的一级缓存的测试:
@Test
public void test1() {
SqlSession session = factory.openSession();
UserMapper userMapper1 = session.getMapper(UserMapper.class);
User user1 = userMapper1.findById(41); //发送sql查询出来,放入一级缓存
System.out.println(user1.getUsername());
User user2 = userMapper1.findById(41); //直接从一级缓存中查询(不发送sql)
System.out.println(user2.getUsername());
session.close(); //session关闭(此session的一级缓存销毁)
SqlSession session2 = factory.openSession();
UserMapper userMapper2 = session2.getMapper(UserMapper.class);
User user3 = userMapper2.findById(41); //发送sql查询一级缓存
System.out.println(user3.getUsername());
}
测试结果分析:
小结
tips:如果更改了一级缓存中的任何数据那么一级缓存会被清空
3.3 二级缓存
3.3.1 介绍
二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession 的。
二级缓存结构图:
首先开启 mybatis的二级缓存。
sqlSession1去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。sqlSession2去查询与 sqlSession1 相同的用户信息, 首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据。如果 SqlSession3 去执行相同 mapper 映射下 sql,执行 commit 提交, 将会清空该 mapper映射下的二级缓存区域的数据。
3.3.2 测试二级缓存
3.3.2.1 第一步:开启二级缓存
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true代表开启二级缓存;为 false 代表不开启二级缓存。
官网介绍:
3.3.2.2 第二步:配置mapper
<mapper namespace="com.itdfbz.dao.UserMapper">
<!--
cache: 表示当前这个mapper对象的查询结果会放入二级缓存
userCache: 表示当前sql语句查询结果是否被存入二级缓存(首先应该配置<cache>标签)
true:存入二级缓存(默认值)
false:不存入二级缓存
-->
<cache></cache>
<select id="findById" parameterType="int" resultType="user" useCache="true">
select * from user where id=#{id}
</select>
</mapper>
将 UserMapper.xml 映射文件中的标签中设置 useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。
注意: 针对每次查询都需要最新的数据 sql,要设置成useCache=false,禁用二级缓存。
3.3.2.3 第三步:实体类实现Serializable
当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口:
3.3.2.4 测试
public void test1() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
SqlSession session1 = factory.openSession();
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.findById(41); //发送sql查询,放入一级缓存
System.out.println(user1);
session1.close(); //关闭一级缓存,并将一级缓存的内容写入二级缓存
SqlSession session2 = factory.openSession();
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user2 = mapper2.findById(41); //从二级缓存查询(反序列化)直接返回(此时一级缓存还是空的)
User user3 = mapper2.findById(41); //查询二级缓存(反序列化)
System.out.println(user3==user2); //false
session2.close();
is.close();
}
测试结果
二级缓存执行原理:
tips:如果更改了任何数据那么二级缓存和一级缓存都将被清空
3.4 MyBatis缓存深入
一级缓存测试:
@Test
public void test2() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
SqlSession session1 = factory.openSession();
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.findById(41); //发送sql查询,放入一级缓存
user1.setAddress("NanChang");
mapper1.update(user1); //清空一级缓存 update delete
User user2 = mapper1.findById(41); //再次发送sql
session1.close(); //关闭一级缓存,并将一级缓存的内容写入二级缓存
}
二级缓存测试:
@Test
public void test3() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
SqlSession session1 = factory.openSession();
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.findById(41); //发送sql查询,放入一级缓存
System.out.println(user1);
session1.close(); //关闭一级缓存,并将一级缓存的内容写入二级缓存
SqlSession session2 = factory.openSession();
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user2 = mapper2.findById(41); //从二级缓存查询(反序列化)直接返回(此时一级缓存还是空的)
mapper2.update(user2); //清空二级缓存、一级缓存
User user3 = mapper2.findById(41); //查询二级缓存--->一级缓存--->数据库
User user4 = mapper2.findById(41); //查询二级缓存(空的)---->查询一级缓存---返回结果
System.out.println(user3 == user4); //true
session2.close();
is.close();
}
3.5 MyBatis缓存总结
一级缓存和二级缓存的执行顺序为:二级缓存—->一级缓存—->数据库
查询语句始终是由一级缓存发送的
一级缓存默认由MyBatis维护,我们只需了解使用即可
二级缓存需要我们开启:
1、在SqlMapConfig.xml中开启二级缓存(默认开启)
<settings>
<!--开启二级缓存,默认是开启状态 false为关闭二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
2、在mapper文件中加入标签代表本mapper文件的所有查询结果放入二级缓存,并保证useCache不为false(默认为true)
<cache></cache>
<select id="findById" parameterType="int" resultType="user" useCache="true">
select * from user where id=#{id}
</select>
3、MyBatis的二级缓存默认采用序列化/反序列化来保证对象的存取,所以所有的entity对象都应该实现serializable
接口
3.6 mybatis自身缓存的弊
A. 分布式的项目架构下,也就是最少使用两个服务器,如果使用两个服务器mybatis的缓存技术就无法在两个服务器通用就是,也就是两个服务器无法达到数据通用,比如我在一个服务器存储了我的信息,但是我转跳到另一个服务器那使用mybatis数据就是需要从新加载,这里就是一个非常大的问题。
B. mybatis无法实现细粒度的缓存管理,当你查询大量数据的时候而且将数据存储到mybatis二级缓存中的时候,但是一旦队一个数据操作增加,删除,修改,这里二级缓存就全部清空,而mybatis无法实现对这里单个信息的修改
问题:如何解决这个缺陷?
答:使用第三方的缓存如:ehcache、redis
3.7.ehcache的整合配置
ehcache需要slf4j这个日志包支持
3.7.1.导入包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
3.7.2.引入缓存配置文件
classpath下添加:ehcache.xml(EhcacheCache实现类的默认配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--diskStore:缓存数据持久化的目录 地址 -->
<diskStore path="F:\temp\cache"/>
<!--
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大
eternal:Element是否永久有效,一但设置了,timeout将不起作用
overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
diskPersistent:是否缓存虚拟机重启期数据
timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,
也就是element存活时间无穷大
memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),
可选的有LFU(最不常使用)和FIFO(先进先出)
-->
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
diskPersistent="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
3.7.3.开启ehcache缓存
EhcacheCache 是ehcache对Cache接口的实现;修改mapper.xml文件,在cache标签的type属性中指定EhcacheCache。覆盖其默认实现
根据需求调整缓存参数:(根据条件对EhcacheCache实现类的参数调整,可选)
<cache type="org.mybatis.caches.ehcache.EhcacheCache" >
<!--最大的空闲时间 -->
<property name="timeToIdleSeconds" value="10000"/>
<!-- 最大的在线时间 -->
<property name="timeToLiveSeconds" value="20000"/>
<!-- 内存的大小 b字节 m1 =1024k 1k=1024b -->
<property name="maxEntriesLocalHeap" value="2000000"/>
<!-- 文件的大小 b字节-->
<property name="maxEntriesLocalDisk" value="20000000"/>
<!-- 算法 LRU:最少使用优先, "LFU" or "FIFO:先进先出 -->
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
结果:观察缓存命中,且在写入磁盘配置路径处可以看到生成文件
4 逆向工程
idea的逆向工程,通过maven的插件来实现
4.1.创建maven项目
4.2. 引入插件mybatis-generator-maven-plugin
在maven项目的pom.xml 添加mybatis-generator-maven-plugin 插件
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
</plugin>
</plugins>
</build>
更新下载依赖包
4.3. generatorConfig.xml
在maven项目下的src/main/resources 目录下建立名为 generatorConfig.xml的配置文件,作为mybatis-generator-maven-plugin 插件的执行目标,模板如下:
<?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="mybatis.properties"/>
<!-- mysql jar 文件位置 -->
<classPathEntry location="D:\.m2\repository\mysql\mysql-connector-java\5.1.35\mysql-connector-java-5.1.35.jar" />
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释,true:是;false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}" userId="${jdbc.username}"
password="${jdbc.password}">
</jdbcConnection>
<!--Oracle数据库的连接信息-->
<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
userId="yycg"
password="yycg">
</jdbcConnection> -->
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="cn.nyse.entity"
targetProject="src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="cn.nyse.mapper"
targetProject="src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!--
targetPackage:mapper接口生成的位置,遵循MyBatis规范,让mapper.xml
和mapper.java在同一目录下
ANNOTATEDMAPPER:注解方式
XMLMAPPER:xml方式
-->
<javaClientGenerator type="XMLMAPPER"
targetPackage="cn.nyse.mapper"
targetProject="src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table tableName="${jdbc.table.items}"></table>
<!-- 有些表的字段需要指定java类型
<table schema="" tableName="">
<columnOverride column="" javaType="" />
</table> -->
</context>
</generatorConfiguration>
mybatis.properties:
<!--jdbc连接数据库配置信息-->
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis
jdbc.username = root
jdbc.password = 123456
#数据库中要生成的表
jdbc.table.items = student
项目目录如下
4.4. 使用maven运行mybatis-generator-maven-plugin插件
观察控制台输出结果:
生成的文件:
<!-- 有些表的字段需要指定java类型
<table schema="" tableName="">
<columnOverride column="" javaType="" />
</table> -->
</context>
mybatis.properties:
```properties
<!--jdbc连接数据库配置信息-->
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis
jdbc.username = root
jdbc.password = 123456
#数据库中要生成的表
jdbc.table.items = student
项目目录如下
4.4. 使用maven运行mybatis-generator-maven-plugin插件
观察控制台输出结果:
生成的文件:
作者:易兮科技 | 来源:https://blog.csdn.net/m0_47157676