Mybatis
文章目录
1. mybatis的使用
1.1 引入依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--插件:用此插件后可以直接在java中的dao包内直接写xml文件-->
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
1.2 简单入门使用
1.2.1创建mybatis主配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
<!--配置 mybatis 环境-->
<environments default="mysql">
<!--id:数据源的名称-->
<environment id="mysql">
<!--配置事务类型:使用 JDBC 事务(使用 Connection 的提交和回
滚)-->
<transactionManager type="JDBC"/>
<!--数据源 dataSource:创建数据库 Connection 对象
type: POOLED 使用数据库的连接池
-->
<dataSource type="POOLED">
<!--连接数据库的四个要素-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--支持中文的url jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8-->
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--告诉 mybatis 要执行的 sql 语句的位置-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mapper class="org.mybatis.builder.AuthorMapper"/>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<package name="org.mybatis.builder"/>
<!-- 使用完全限定资源定位符(URL) -->
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
</configuration>
1.2.2编写dao接口的映射文件
要 StudentDao.xml 文件名称和接口 StudentDao 一样,区分大小写。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace:必须有值,自定义的唯一字符串
推荐使用:dao 接口的全限定名称
--> <mapper namespace="com.bjpowernode.dao.StudentDao">
<!--
<select>: 查询数据, 标签中必须是 select 语句
id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称,
使用名称表示要执行的 sql 语句
resultType: 查询语句的返回结果数据类型,使用全限定类名
-->
<select id="selectStudents"
resultType="com.bjpowernode.domain.Student">
<!--要执行的 sql 语句-->
select id,name,email,age from student
</select>
</mapper>
1.2.3配置日志功能
在主配置文件中加入
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
1.2.4测试方法
使用sqlsession执行操作时,需要知道 接口全类名 以及 调用的方法,返回值。
创建sqlsession时,若使用factory.openSession(),则需要手动提交事物:sqlsession.commit() ,
使用factory.openSession(true)则会自动帮我们提交事物。
@Test
public void testInsert() throws IOException {
//1.mybatis 主配置文件
String config = "mybatis-config.xml";
//2.读取配置文件
InputStream in = Resources.getResourceAsStream(config);
//3.创建 SqlSessionFactory 对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取 SqlSession
SqlSession session = factory.openSession();
//5.创建保存数据的对象
Student student = new Student();
student.setId(1005);
student.setName("张丽");
student.setEmail("zhangli@163.com");
student.setAge(20);
//6.执行插入 insert
int rows = session.insert(
"com.bjpowernode.dao.StudentDao.insertStudent",student);
//7.提交事务
session.commit();
System.out.println("增加记录的行数:"+rows);
//8.关闭 SqlSession
session.close();
}
1.3 使用对象的介绍
**1.Resources **
Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象。
2. SqlSessionFactoryBuilder
SqlSessionFactory 的创建,需要使用 SqlSessionFactoryBuilder 对象的build()方法。由于 SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁。所以,一般会将该 SqlSessionFactoryBuilder对象创建为一个方法内的局部对象,方法结束,对象销毁。
3.SqlSessionFactory 接口
SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用只需要一个该对象即可。创建 SqlSession 需要使用SqlSessionFactory 接口的的 openSession()方法。
-
openSession(true):创建一个有自动提交功能的 SqlSession
-
openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交
-
openSession():同 openSession(false)
4.SqlSession 接口
SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以 SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。
SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将其关闭。再次需要会话,再次创建。 SqlSession在方法内部创建,使用完毕后关闭。
1.4 mybatis工具类
public class MyBatisUtil {
//定义 SqlSessionFactory
private static SqlSessionFactory factory = null;
static {
//使用 静态块 创建一次 SqlSessionFactory
try{
String config = "mybatis-config.xml";
//读取配置文件
InputStream in = Resources.getResourceAsStream(config);
//创建 SqlSessionFactory 对象
factory = new SqlSessionFactoryBuilder().build(in);
}catch (Exception e){
factory = null;
e.printStackTrace();
}
}
/* 获取 SqlSession 对象 */
public static SqlSession getSqlSession(){
SqlSession session = null;
if( factory != null){
session = factory.openSession();
}
return session;
} }
2. 类型别名
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
在主配置文件中加入:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
每一个在包 domain.blog
中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author
的别名为 author
;若有注解,则别名为其注解值。见下面的例子:
@Alias("author")
public class Author {
...
}
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
2.1 parameterType
接口中方法参数的类型, 类型的完全限定名或别名。这个属性是可选的 ,因为 MyBatis 可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从 java 代码传入到 mapper 文件的 sql 语句。
<insert id="addArea">
insert into area values(null,#{areaName},#{areaLevel},#{parentId})
</insert>
//没有写参数和返回值类型,依然执行成功
TestDao mapper = sqlSession.getMapper(TestDao.class);
Area area = new Area(null,"1",2,3);
Integer integer = mapper.addArea(area);
sqlSession.commit();
2.2 只有一个参数
Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String),占位符 #{ 任意字符 },和方法的参数名无关。
Student selectById(int id);
mapper 文件:
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
#{studentId} , studentId 是自定义的变量名称,和方法参数名无关。
2.3 多个简单参数param
当 Dao 接口方法多个参数,需要通过名称使用参数。 在方法形参前面加入@Param(“自定义参数名”),mapper 文件使用#{自定义参数名}。
List<Student> selectMultiParam(@Param("personName") String name,
@Param("personAge") int age);
mapper 文件:
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{personName} or age =#{personAge}
</select>
2.4 参数是对象
当有多个参数时,我们可以使用对象进行传值,会根据对象的get方法进行取值。而sql语句中的占位符就写 #{对象的属性名},并且只关心对象中有没有对应的get方法,不关心对象类型。
因此产生了一个小窍门,既然不关心对象类型,只关心是否能get到需要的属性,那我们可以把多个参数put到一个map集合中,传递map集合给sql语句就行了。
2.5 多个参数-按位置
参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0},第二个是#{arg1}
注意:mybatis-3.3 版本和之前的版本使用#{0},#{1}方式, 从 mybatis3.4 开始使用#{arg0}方式。
List<Student> selectByNameAndAge(String name,int age);
mapper 文件
<select id="selectByNameAndAge"
resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{arg0} or age
=#{arg1}
</select>
2.6 多个参数-使用 Map
List<Student> selectMultiMap(Map<String,Object> map);
mapper 文件:
<select id="selectMultiMap" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{myname} or age
=#{myage}
</select>
测试方法:
@Test
public void testSelectMultiMap(){
Map<String,Object> data = new HashMap<>();
data.put("myname","李力");// #{myname}
data.put("myage",20); // #{myage}
List<Student> stuList = studentDao.selectMultiMap(data);
stuList.forEach( stu -> System.out.println(stu));
}
2.7. #和$
# :占位符,告诉 mybatis 使用实际的参数值代替。并使用PrepareStatement 对象执行 sql 语句, #{…}代替 sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法。一般写在’='右边
**$ ** 字符串替换,告诉 mybatis 使用$包含的“字符串”替换所在位置。使用
Statement 把 sql 语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作,会有sql注入的风险,可以用来改变sql语句的结构。
注意:当使用 占 位 符 时 , 即 使 只 有 一 个 参 数 , 也 不 能 随 便 写 占位符时,即使只有一个参数,也不能随便写 占位符时,即使只有一个参数,也不能随便写(这里不能写任意值)。需要在接口中使用@param(“指定名”)的方式,$(“指定名”)。
3. 封装 MyBatis 输出结果
3.1 resultType
resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HYqZHNtP-1628853372744)(image/image.png)]
3.1.1 简单类型
int countStudent();
mapper 文件:
<select id="countStudent" resultType="int">
select count(*) from student
</select>
测试方法:
@Test
public void testRetunInt(){
int count = studentDao.countStudent();
System.out.println("学生总人数:"+ count);
}
3.1.2 对象类型
接口方法:
Student selectById(int id);
mapper 文件:
<select id="selectById" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
框架的处理: 使用构造方法创建对象。调用 setXXX 给属性赋值。
Student student = new Student()
注意:Dao 接口方法返回是集合类型,需要指定集合中的类型,不是集合本身。
3.1.3 map类型
sql 的查询结果作为 Map 的 key 和 value。推荐使用Map<Object,Object>。
注意:Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录是错误
3.1.4 多条数据的map
<select id="findUserListMapByName" resultType="com.jiangwei.mybatis.entity.Userinfo">
select * from userinfo
<where>
<if test="uname!=null and ''!=uname">
uname like concat('%',#{uname},'%')
</if>
</where>
</select>
<!--指定key展示哪个列-->
@MapKey("uid")
Map<Integer,Userinfo> findUserListMapByName(String uname);
3.1.5 插入返回id
<insert id="insertTestMYbatis" useGeneratedKeys="true"keyProperty="id" keyColumn="id"">
insert into test_mybatis (name, age) values (#{name},#{age})
</insert>
3.2 ResultMap
用于处理列名与属性名不同的情况
resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。
常用在列名和 java 对象属性名不一样的情况。
接口方法:
List<Student> selectUseResultMap(QueryParam param);
mapper 文件:
<!-- 创建 resultMap
id:自定义的唯一名称,在<select>使用
type:期望转为的 java 对象的全限定名称或别名
--><resultMap id="studentMap" type="com.bjpowernode.domain.Student">
<!-- 主键字段使用 id -->
<id column="id" property="id" />
<!--非主键字段使用 result-->
<result column="name" property="name"/>
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<!--resultMap: resultMap 标签中的 id 属性值--> <select id="selectUseResultMap" resultMap="studentMap">
select id,name,email,age from student where name=#{queryName} or
age=#{queryAge}
</select>
其实使用resultType也可以处理列名与属性名不同的情况,我们可以给数据的列名取一个与属性名相同的别名就行了。
4. 模糊查询
模糊查询的实现有两种方式, 一是 java 代码中给查询数据加上“%” ; 二是在 mapper 文件 sql 语句的条件位置加上“%”,推荐第一种方式,更加灵活。
<select id="findUserByCondition" resultType="com.jiangwei.mybatis.entity.Userinfo">
select * from userinfo
<where>
<if test="uname!=null and ''!=uname">
uname like "%" #{uname} '%'
<!-- uname like concat('%',#{uname},'%')-->
</if>
<if test="sex!=null">
sex = #{sex}
</if>
<if test=" phone !=null">
phone like '%${phone}%'
</if>
<if test=" createtime !=null">
createtime = #{createtime}
</if>
</where>
</select>
5. 动态sql
在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。
5.1 SQL 之
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
where 1=1
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="age > 0 ">
and age > #{age}
</if>
</select>
5.2 SQL 之
使用标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。需要注意的是,第一个标签中的SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and去掉。但其它中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
<select id="selectStudentWhere"
resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
<where>
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="age > 0 ">
and age > #{age}
</if>
</where>
</select>
5.3 SQL 之
标签用于实现对于数组与集合的遍历。对其使用,需要注意: collection 表示要遍历的集合类型, list ,array 等。 open、close、separator 为对遍历内容的 SQL 拼接。
<select id="selectStudentForList"
resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
<if test="list !=null and list.size > 0 ">
where id in
<foreach collection="list" open="(" close=")" item="stuid" separator=",">
#{stuid}
</foreach>
</if>
</select>
当list中存的是对象时:
<select id="selectStudentForList2"
resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
<if test="list !=null and list.size > 0 ">
where id in
<foreach collection="list" open="(" close=")"
item="stuobject" separator=",">
#{stuobject.id}
</foreach>
</if>
</select>
5.4 SQL 之代码片段
<!--创建 sql 片段 id:片段的自定义名称-->
<sql id="studentSql">
select id,name,email,age from student
</sql>
<select id="selectStudentSqlFragment"
resultType="com.bjpowernode.domain.Student">
<!-- 引用 sql 片段 -->
<include refid="studentSql"/>
<if test="list !=null and list.size > 0 ">
where id in
<foreach collection="list" open="(" close=")" item="stuobject" separator=",">
#{stuobject.id}
</foreach>
</if>
</select>
6. mybatis的延迟加载
生效:mybatis中的延迟加载仅在有二次查询的场景下生效.
延迟加载目的:减少无效的数据库查询操作,提高响应的效率。
延迟加载:分页,树形结构数据,前端图片的延迟加载
<setting name="lazyLoadingEnabled" value="true"></setting>
<!-- <setting name="aggressiveLazyLoading" value="false"></setting>
<setting name="lazyLoadTriggerMethods" value=""></setting>-->
@Test
public void test2_selectUserContainRoleByUid(){
SysuserMapper mapper = sqlSession.getMapper(SysuserMapper.class);
Sysuser sysuser = mapper.selectUserById(1);
// System.out.println("mapper ===="+sysuser);
}
7. 关联查询
https://www.jianshu.com/p/ae60478c3dc0
8. 缓存
mybatis缓存
cache:减少数据库的重复查询操作.基于内存把第一次查询的结果保存的缓存对象中,当后续查询时,先查询缓存,缓存中有则返回;缓存中没有则查询数据库,并把查询结果放缓存。
ehcache 占用web服务器的内存(一般不用)
memercache,redis 独立部署的缓存
mybatis的缓存分为两级:
session级别缓存:默认开启
factory级别缓存:默认未开启.
一级缓存:
//在web系统中,每次用户请求,后端开启sqlsession,查询完毕,session关闭.
@Test
public void test1_selectOne(){
SysuserMapper mapper = sqlSession.getMapper(SysuserMapper.class);
Sysuser sysuser = mapper.selectUserByKey(1);
sqlSession.clearCache();//清理缓存
Sysuser sysuser1 = mapper.selectUserByKey(1);
System.out.println("mapper ===="+sysuser);
}
二级缓存:
不同的两个人去查,可以命中缓存
<setting name="cacheEnabled" value="true"></setting>
<!–缓存策略,只对当前namespace下的所有查询全部生效,可以再select中加usecache禁用二级缓存,可以在update,delete中使用flushcache强制清空缓存–>
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
@Test
public void test1_selectOne(){
SysuserMapper mapper = sqlSession.getMapper(SysuserMapper.class);
Sysuser sysuser = mapper.selectUserByKey(1);
// sqlSession.clearCache();//清理缓存
// Sysuser sysuser1 = mapper.selectUserByKey(1);
System.out.println("mapper ===="+sysuser);
sqlSession.close();
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SysuserMapper mapper1 = sqlSession1.getMapper(SysuserMapper.class);
Sysuser sysuser2 = mapper1.selectUserByKey(1);
sqlSession1.close();
}
9. mybatis generater
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<?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="database.properties"></properties>
<!-- 数据库驱动包(如果classpath下已有则可以忽略) -->
<!--<classPathEntry location="D:/SQL/mysql-8.0.22-winx64/mysql-connector-java-8.0.15.jar"/>-->
<!--MBG上下文配置
id: 上下文id
TODO: 选择合适的targetRuntime
targetRuntime: 指定要按照哪种形式去生成Java代码, 默认值Mybatis3
Mybatis3 生成基本的增删改查, 还会生成"xxxByExample"方法的动态SQL
MyBatis3Simple 只生成基本的增删改查
defaultModelType: 要如何生成实体类, 默认值conditional
conditional 和hierarchical类似, 只是当主键列只有一个时, 不会生成只包含主键的实体类
flat 只为每张表生成一个实体类(推荐使用)
hierarchical 生成三个实体类, 一个只包含主键, 一个只包含BLOB字段, 一个包含其他剩余字段
-->
<context id="MyGenerator" targetRuntime="Mybatis3" defaultModelType="flat">
<!-- 自动给关键字添加分隔符 -->
<property name="autoDelimitKeywords" value="true"/>
<!-- 前缀分隔符 -->
<property name="beginningDelimiter" value="`"/>
<!-- 后置分隔符 -->
<property name="endingDelimiter" value="`"/>
<!-- Java文件编码 -->
<property name="javaFileEncoding" value="UTF-8"/>
<!-- Java文件格式 -->
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
<!-- XML文件格式 -->
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>
<!-- TODO: 根据个人需求选择合适的插件 -->
<!-- 生成xxxMapper.xml时覆盖原文件, 而不是追加 -->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<!-- 生成Equals和HashCode方法 -->
<!--<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"/>-->
<!-- 实现Serializable接口 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!-- 生成toString方法 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!--生成注释-->
<commentGenerator>
<!-- 完全禁止生成注释 -->
<property name="suppressAllComments" value="true"/>
<!-- 禁止生成时间戳注释 -->
<property name="suppressDate" value="true"/>
<!-- 时间戳格式, 要符合SimpleDateFormat -->
<!--<property name="dateFormat" value="yyyy/MM/dd HH:mm:ss"/>-->
<!-- 注释是否包含对应表名或列名信息 -->
<!--<property name="addRemarkComments" value="true"/>-->
</commentGenerator>
<!-- TODO: 配置MySQL数据库连接 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC"
userId="root"
password="root">
<!-- 避免MySQL多次生成SQL映射文件 -->
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!-- 设置JDBC类型和Java类型的映射 -->
<javaTypeResolver>
<!-- true:使用BigDecimal对应DECIMAL和NUMERIC数据类型
false:默认值
scale>0;length>18:使用BigDecimal;
scale=0;length[10,18]:使用Long;
scale=0;length[5,9]:使用Integer;
scale=0;length<5:使用Short -->
<property name="forceBigDecimals" value="false"/>
<!-- 是否应该符合JSR-310日期类型, 还是说直接将日期映射成java.util.Date -->
<property name="useJSR310Types" value="false"/>
</javaTypeResolver>
<!-- TODO: 生成Model实体类
targetProject: 项目源码根目录
targetPackage: 生成的实体类放在哪个包里
-->
<javaModelGenerator targetPackage="pers.oneice.ssm.crud.pojo" targetProject="src/main/java">
<!-- 是否直接将实体类放在targetPackage包中(废话...) -->
<property name="enableSubPackages" value="true"/>
<!-- 是否生成有参构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 是否删除查询结果的前后空格(体现在实体类的set方法中) -->
<property name="trimStrings" value="false"/>
<!-- 生成的实体类属性是否不可变 -->
<property name="immutable" value="false"/>
<!-- 设置所有实体类的基类 -->
<!--<property name="rootClass" value=""/>-->
</javaModelGenerator>
<!-- TODO: 生成SQL映射文件 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- TODO: 生成映射器接口 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="pers.oneice.ssm.crud.dao" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- TODO: 要逆向分析的表, 多张表需要配置多个table标签
tableName: 表名
domainObjectName: 要生成的实体类名称, 会影响【实体类/映射器接口/映射文件】的名称
可选属性:
alias: 设置【表别名】和【列别名前缀】
mapperName: 设置【映射器接口】和【映射文件】的名称
enableXxx: 是否要为映射器生成Xxx方法, 默认true
-->
<table tableName="tb_dept" domainObjectName="Department">
<!-- 插入数据之后获取自增主键值 -->
<generatedKey column="dept_id" identity="true" type="post" sqlStatement="MySql"/>
<!-- 重写列和属性的映射 -->
<!--<columnOverride property="propertyName" column="LONG_VARCHAR_FIELD" javaType="java.lang.String" jdbcType="VARCHAR"/>-->
<!-- 忽略某些列的映射 -->
<!--<ignoreColumn column=""/>-->
</table>
<table tableName="tb_emp" domainObjectName="Employee">
<!-- 插入数据之后获取自增主键值 -->
<generatedKey column="emp_id" identity="true" type="post" sqlStatement="MySql"/>
<!-- 重写列和属性的映射 -->
<columnOverride property="gender" column="gender" javaType="java.lang.Integer"
jdbcType="TINYINT"/>
</table>
</context>
</generatorConfiguration>
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
如果要增加关联查询
public interface EmployeeMapperExt extends EmployeeMapper {
List<Employee> selectWithDeptByExample(EmployeeExample example);
}
<?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.jiangwei.dao.EmployeeMapperExt">
<resultMap id="EmpResultMapWithDept" type="Employee" extends="com.jiangwei.dao.EmployeeMapper.BaseResultMap">
<association property="dept" javaType="Dept" resultMap="com.jiangwei.dao.DeptMapper.BaseResultMap">
</association>
</resultMap>
<sql id="Emp_With_Dept_Column_list">
e.eid,
e.ename,
e.password,
e.createdate,
e.dept_id,
d.did,
d.name
</sql>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<select id="selectWithDeptByExample" resultMap="EmpResultMapWithDept">
select
<include refid="Emp_With_Dept_Column_list"/>
from employee e left join dept d on e.dept_id=d.did
<if test="_parameter != null">
<include refid="Example_Where_Clause"/>
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
</mapper>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hqEut5nR-1628853372755)(image/image_3.png)]
10. 分页插件
https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.1</version>
</dependency>
在mybatis主配置文件中
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
reasonable
:分页合理化参数,默认值为false
。当该参数设置为 true
时,pageNum<=0
时会查询第一页,pageNum>pages
(超过总数时),会查询最后一页。默认false
时,直接根据参数进行查询。
也可以在spring配置文件中配置拦截器插件
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注意其他配置 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
params=value1
</value>
</property>
</bean>
</array>
</property>
</bean>
//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
//紧跟着的第一个select方法会被分页
List<User> list = userMapper.selectIf(1);