Top:MyBatis框架
https://mybatis.net.cn/
参考文档mybatis 是一个
持久层框架
主要用于来对
数据库进行操作
mybtais
底层还是对jdbc的封装
mybatis是一个
ORM 映射的框架
O ==> 对象
R ==> 数据库表
M ==> 映射
mybatis 能够实现数据库表(列)
与对象(属性)
的映射关系
一、Mybatis 的优势
- 相对于传统的jdbc来进行开发,代码量少了百分之五十
- 它是一个orm映射框架,能够实现数据库表与对应的映射
- mybatis 框架支持动态sql语句,提供了一些动态的标签
- mybatis 轻量级,操作起来比较简单
- mybatis 框架实现sql与代码分离,便于后台代码的扩展与维护
二、MyBatis框架的前期搭建
(一) idea中 mybatis插件安装
在plugins -> 下载MyBatisX插件 -> 勾选使用
(二)idea中xml模板创建
在setting -> File and Code Template -> Files -> +
1. Mapper的约束
<?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">
2. Config的约束
<?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">
(三)数据库配置文件引入
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/数据库名称?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root
三、MyBatis正式搭建
1.新建数据库 新建表
2.创建项目导入响应的依赖(jar)
3.新建一个实体Bean
4.编写核心配置文件编写mapper映射关系的配置文件
(二) 核心jar包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
(四)核心配置文件
- 给实体类自定义命名
- 配置多个环境
- el 引入数据库(数据源)
- 映射文件的关联方式
<?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>
<properties resource="jdbcConfig.properties"/>
<typeAliases>
<!-- 给实体类自定义命名 -->
<!--单个的来设置别名-->
<!-- < type="com.qf.entity.UsertypeAlias" alias="user"/>-->
<!--包下所有实体类设置别名 别名默认是首字母小写 user-->
<package name="com.qf.entity"/>
</typeAliases>
<!-- 配置多个环境-->
<environments default="mysql">
<!-- 配置mysql环境-->
<environment id="mysql">
<!-- 事务管理器-->
<transactionManager type="JDBC"/>
<!-- 数据源-->
<dataSource type="POOLED">
<!-- 当配置好数据库的properties属性后,可以通过 el表达式来获取配置文件的信息-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 映射文件的关联方式-->
<!-- 通过文件类路径引入映射文件-->
<mapper resource="com/qf/mapper/UserMapper.xml" />
<!-- 用类注册引入映射器接口(一般注解的时候使用)-->
<!-- <mapper class="com.qf.mapper.UserMapper"/>-->
<!-- 通过包名引入映射器接口(一般注解的时候使用)-->
<!-- <package name="com.qf.mapper"/>-->
<mapper resource="com/qf/mapper/AdminMapper.xml" />
<mapper resource="com/qf/mapper/StudentMapper.xml" />
</mappers>
</configuration>
1. 核心配置文件xml目录结构
2. MybatisConfig.xml具体解释
POOLED
and UNPOOLED
1.environments ==>表示环境的配置 可以配置多个环境
2.environment id="mysql" 指定是mysql的环境
3.transactionManager 配置事务管理器
4.type
JDBC:表示使用jdbc 的方式来进行事务的管理
MANAGED:没有做任何操作 依赖于容器 以容器的方式的来进行事务管理
spring +mybatis ==设置参数MANAGED 表示已容器spring的方式来进行事务的管理
5.dataSource ==>数据源
POOLED ==> 表示一连接池的方式来管理连接 不会反复的创建与销毁连接
UNPOOLED ==> 不是以连接池的方式来进行管理连接 使用的时候都创建连接与销毁连接
JNDI==>必须在web环境,依赖于web容器 在tomcat 中可以进行配置(重点)
(五)mapper映射关系的配置文件
1.namespace ==>命名空间 完整的包名+类名
2.<select>查询 <insert> 增加 <update> 修改 <delete>删除
3.id==>对应的是mapper方法的名称
4.parameterType==>参数类型
5.resultType==>返回值类型
(六)举例 . 基本的增删改查
(配置UserMapper.xml文件)
<!--
实体类Bean(User)的全路径:
com.qf.entity.User
持久层Dao(UserMapper)的全路径:
com.qf.mapper.UserMapper
-->
<select id="selectAll" resultType="user">
select * from user
</select>
<insert id="insertUser" parameterType="user">
insert into user(uname,upwd,udate)values(#{uname},#{upwd},#{udate})
</insert>
<update id="updateUserByUid" parameterType="user">
update user set uname=#{uname},upwd=#{upwd},udate=#{udate} where uid=#{uid}
</update>
<delete id="deleteUserByUid" parameterType="int">
delete from user where uid=#{uid}
</delete>
<select id="selectUserByUid" parameterType="int" resultType="user">
select * from user where uid=#{uid}
</select>
(七)举例 . 测试类
package com.qf.test;
import com.qf.entity.User;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Test01 {
//普通写法
@Test
public void selectAllTest01() throws IOException {
//获取mybatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
//获取工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//通过工厂对象获取SqlSession
SqlSession sqlSession = factory.openSession(true);
//调用方法 执行数据库操作 完整包名+类名+方法名称
List<User> userList = sqlSession.selectList("com.qf.mapper.UserMapper.selectAll");
for (User u : userList) {
System.out.println(u);
}
}
//动态代理写法
public void selectAllTest02() throws IOException {
//获取mybatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
//获取工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//通过工厂对象获取SqlSession
SqlSession sqlSession = factory.openSession(true);
//调用方法 执行数据库操作
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.selectAll();
userList.foreach(user->System.out::Println)
}
}
四、工具类的抽取
(一)新建一个SqlSessionFactoryUtils工具类
package com.qf.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @author:lyz
* @since: jdk 1.8
**/
public enum SqlSessionFactoryUtils {
SSFU;//枚举型
private SqlSessionFactory sqlSessionFactory;
SqlSessionFactoryUtils(){
//try-catch快捷键捕获:Ctrl+Win+Alt+t
try {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
//定义一个公有的方法返回sqlSessionFactory
public SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
(二)新建一个CommentMapper
package com.qf.utils;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
/**
* @author:lyz
* @since: jdk 1.8
**/
public class CommentMapper {
public SqlSession sqlSession;
@Before
public void before(){
sqlSession=SqlSessionFactoryUtils.SSFU.getSqlSessionFactory().openSession(true);
}
@After
public void after(){
sqlSession.close();
}
}
(三)抽取工具类后的测试类(举例)
package com.qf.test;
import com.qf.entity.User;
import com.qf.mapper.UserMapper;
import com.qf.utils.CommentMapper;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author:lyz
* @since: jdk 1.8
**/
public class UserMapperTest extends CommentMapper {
// 基础增删改查
@Test
public void selectAll() throws IOException {
List<User> userList = sqlSession.selectList("com.qf.mapper.UserMapper.selectAll");
for (User u : userList) {
System.out.println(u);
}
}
@Test
public void insertUser(){
User user=new User();
user.setUname("ccc");
user.setUpwd("123");
user.setUdate(LocalDateTime.now());
int num=sqlSession.insert("com.qf.mapper.UserMapper.insertUser",user);
System.out.println(num);
}
@Test
public void updateUserByUid(){
User user=new User();
user.setUname("test");
user.setUpwd("test");
user.setUdate(LocalDateTime.now());
int num = sqlSession.update("com.qf.mapper.UserMapper.updateUser",user);
System.out.println(num);
}
@Test
public void deleteUserByUid(){
int num=sqlSession.delete("com.qf.mapper.UserMapper.deleteUser",6);
System.out.println(num);
}
@Test
public void selectUserByUid(){
/*User u = sqlSession.selectOne("com.qf.mapper.UserMapper.selectUserByUid", 1);
System.out.println(u);*/
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectUserByUid(1);
System.out.println(user);
}
}
五、①常见问题
(一)查询的时候传递多参
<!-- 查询的时候传递多参-->
<!--方法一:arg0~arg* 依次获取传递进来的参数-->
<!-- 直接#{} 如何arg 再根据传递过来的参数顺序获取值(从0开始获取)-->
<select id="selectUserByUidAndUName01" resultType="user">
select * from user where uid=#{arg0} and uname=#{arg1}
</select>
<!--方法二:使用 map集合-->
<!-- new HashMap(),以键值对的方式存储,在通过键值对的方式获取-->
<!-- 其中键可以任意取名,只要获取值的时候对应好就行-->
<select id="selectUserByUidAndUName02" resultType="user">
select * from user where uid=#{key0} and uname=#{key1}
</select>
<!--方法三:通过注解--> <!--建议使用这种-->
<!-- 在定义方法的时候就给要传入的参数用 @Param()标记上-->
<!-- 然后在@Param("自定义命名的位置")内自定义其传入参数的别名,用于sql语句读取的时候通过别名调用-->
<select id="selectUserByUidAndUName03" resultType="user">
select * from user where uid=#{uid} and uname=#{sb}
</select>
<!--方法四:通过对象的属性名(自动查找)-->
<select id="selectUserByUidAndUName04" parameterType="user" resultType="user">
select * from user where uid=#{uid} and uname=#{uname}
</select>
(二)模糊查询
为了尽可能避免sql注入问题,建议使用
concat(…)
拼接
<!-- 模糊查询-->
<!--方法一:占位符?式插入-->
<select id="selectUserLikeUName01" resultType="com.qf.entity.User">
select * from user where uname like #{uname}
</select>
<!--方法二:sql拼接式插入(会产生sql注入问题 ==延申出来的问题==》 #{}与${}的区别)-->
<select id="selectUserLikeUName02" resultType="com.qf.entity.User">
select * from user where uname like '%${uname}%'
</select>
<!--方法三:调用concat(……)方法--> <!--建议使用这种-->
<select id="selectUserLikeUName03" resultType="com.qf.entity.User">
select * from user where uname like concat("%",#{uname},"%")
</select>
(三)数据库列名与实体类属性名不一致
myabtis是一个orm映射的框架 数据库的列名对应实体类的属性。如果数据库的列名与实体类的属性对应不上
就获取不到值,这个时候就得用到使用resultMap
1. 数据库列名as实体类属性
2. 调用resultMap
<!-- 补充: -->
<!-- resultMap : 用于自定义返回结果集
id特例必须用 id标签去写
其他元素用 result去写
(写的内容为 实体类属性 与 数据库表的列名 用以相互对应)
property : 实体类属性
column : 数据库表的列名
-->
<!-- 数据库列名与实体类属性名不一致的时候,可以在执行语句的时候-->
<!--方法一:数据库列名as实体类属性 -->
<!-- 给数据库的列名 as为 实体类的属性名-->
<!-- 同时给数据库的表,起别名 方便调用其属性值-->
<select id="selectAllAdmin01" resultType="com.qf.entity.Admin">
select a.aid,a.name as adminName,a.pwd as adminPwd,a.date as dateTime from admin a
</select>
<!--方法二:调用resultMap --> <!--建议使用这种-->
<!-- 其中 resultMap中的 id必须式唯一的(用于辨认对应的 resultMap值)-->
<!-- property属性名 column表列名-->
<resultMap id="selectAllAdmin02ResultMap" type="admin">
<id property="aid" column="aid"></id>
<result property="adminName" column="name"></result>
<result property="adminPwd" column="pwd"></result>
<result property="dateTime" column="date"></result>
</resultMap>
<select id="selectAllAdmin02" resultMap="selectAllAdmin02ResultMap">
select * from admin a
</select>
(四)主键回填
1. 标签属性解释
keyColumn ==>数据库表中主键的列名
keyProperty==>实体类的属性
resultType ==> 返回值类型
order AFTER/BEFORE 在增加后或者是在增加前执行这个sql语句
select last_insert_id() ==>表示查询出当前表中 最后的id 值
select replace(UUID(),"-","") ==>表示查询出当前表中,回填的UUID值,同时将UUID中的"-"换成""
select "???" ==>表示查询出当前表中,回填的值,同时将其直接更换成为"???"
2.回填int类型
使用场景
: 在插入数据成功之,需要立即获取查询当前数据的id,但是在数据库中一般都是主键是自增长,这种场景就可以使用主键回填。
例如二阶段的项目 生成订单成功之后 需要动态修改购物车的数据
3.回填String类型
<!-- 主键回填一:回填int类型的id-->
<!-- 这样能够自增长的id在执行完语句后,会返还到对象中,我们也可以从中调用到。
如果没进行id的主键回填的话,我们只能获取到id对应的int类型 的默认值0-->
<insert id="insertUser1" parameterType="user">
<selectKey keyColumn="uid" keyProperty="uid" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into user(uname,upwd,udate)values(#{uname},#{upwd},#{udate})
</insert>
<!-- 主键回填二:回填String类型的uname-->
<!-- select replace(UUID(),"-","")
在执行sql语句之前,将uname的回填数据更改为UUID(),同时将UUID中的"-"换成""
select replace("???","niuzi","what")
在执行sql语句之前,将uname的回填数据更改为"???",同时将其中的"niuzi"换成"what"
select "???"
在执行sql语句之前,将uname的回填数据直接更换成为"???"
-->
<insert id="insertUser2" parameterType="user">
<selectKey keyColumn="uname" keyProperty="uname" resultType="String" order="BEFORE" >
select "???"
</selectKey>
insert into user(uname,upwd,udate)values(#{uname},#{upwd},#{udate})
</insert>
(五)sql片段
把部分常用的sql语句,提取出来,构建成片段,多次使用。
使用场景
:用于sql公共代码的提取 一般用于查询比较多
<!-- sql片段:把部分常用的sql语句提取出来构建成片段多次使用-->
<sql id="userNWD">uname,upwd</sql>
<select id="selectUser3" resultType="com.qf.entity.User">
select <include refid="userNWD"/> from user
</select>
六、MyBatis处理关联关系-多表连接
实体间的关系:关联关系(拥有 has、属于 belong)
OneToOne:一对一关系(Passenger— Passport)
OneToMany:一对多关系(Employee — Department)
ManyToMany:多对多关系(Student — Subject)
(零)Bean的实例
package com.qf.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author:lyz
* @since: jdk 1.8
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int uid;
private String uname;
private LocalDateTime ubirthday;
private String usex;
//一对一 关系映射 (数据库内关系)
private Card card;
//一对多 关系映射 (数据库内关系)
private List<Order> orderList;
//多对多 关系映射 (数据库内关系)
private List<Role> roleList;
}
(一)普通多表关联
1. 一对一
<!-- 一对一 -->
<!-- 一对一连接的时候,返回自定义返回结果集 内要附加 association-->
<!-- association “同行内”要填 property(实体类内与该表关联的 关系映射属性是哪一个)
column(通过数据库内该表的那个列名 去进行关系映射)
(一对一的要填) javaType(用于说明和那个表相关连)
-->
<!-- association “内部”要填 被该表相关连的“javaType外表”
实体类属性 与 数据库表的列名 相互对应的关系-->
<resultMap id="selectOneByOneMap" type="user">
<id column="uid" property="uid"/>
<result column="uname" property="uname"/>
<result column="ubirthday" property="ubirthday"/>
<result column="usex" property="usex"/>
<association property="card" column="uid" javaType="card">
<id column="cid" property="cid"/>
<result column="cnumid" property="cnumid"/>
<result column="uid" property="uid"/>
</association>
</resultMap>
<select id="selectOneByOne" resultMap="selectOneByOneMap">
select u.*,c.cnumid from `user` u,card c where u.uid=c.cid
</select>
2. 一对多
<!-- 一对多 -->
<!-- 一对多连接,返回自定义结果集 内要附加 collection-->
<!-- collection “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
column(通过数据库内该表的那个列名 去进行关系映射)
(一对多的要填) ofType(用于说明和那个表相关连)
-->
<!-- collection “内部”要填 被该表相关连的“ofType”
实体类属性 与 数据库表的列名 相互对应的关系-->
<resultMap id="selectOneByManyMap" type="user">
<id column="uid" property="uid"/>
<result column="uname" property="uname"/>
<result column="ubirthday" property="ubirthday"/>
<result column="usex" property="usex"/>
<collection property="orderList" column="uid" ofType="order">
<id column="oid" property="oid"/>
<result column="oname" property="oname"/>
<result column="uid" property="uid"/>
</collection>
</resultMap>
<select id="selectOneByMany" resultMap="selectOneByManyMap">
select u.*,o.* from `user` u inner join `order` o on u.uid=o.uid
</select>
3. 多对多(need 中间表)
<!-- 多对多 (需要借助中间表) -->
<!-- 多对多连接,返回自定义结果集 内要附加 collection-->
<!-- collection “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
column(通过数据库内该表的那个列名 去进行关系映射)
(一对多的要填) ofType(用于说明和那个表相关连)
-->
<!-- collection “内部”要填 被该表相关连的“ofType”
实体类属性 与 数据库表的列名 相互对应的关系-->
<resultMap id="selectManyByManyMap" type="user">
<id column="uid" property="uid"/>
<result column="uname" property="uname"/>
<result column="ubirthday" property="ubirthday"/>
<result column="usex" property="usex"/>
<collection property="roleList" column="uid" ofType="role">
<id column="rid" property="rid"/>
<result column="rname" property="rname"/>
<result property="rdesc" column="rdesc"/>
</collection>
</resultMap>
<select id="selectManyByMany" resultMap="selectManyByManyMap">
select * from `user` u
inner join u_r ur on u.uid=ur.uid
inner join role r on ur.rid=r.rid
</select>
(二)嵌套多表关联
1. 嵌套一对一
<!-- 嵌套一对一 -->
<!-- 一对一连接,返回自定义结果集 内要附加 association-->
<!-- association “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
column(通过数据库内该表的那个列名 去进行关系映射)
(一对一的要填) javaType(用于说明和那个表相关连)
(嵌套的需要额外加) select(所嵌套方法的全路径“相当于先执行目前的sql命令,
然后再把column内数据传过去,充当参数,执行下一个sql命令”)
-->
<!-- 嵌套的话 association “内部”不需要填写内容要填-->
<resultMap id="selectOneByOneQianQianMap" type="user">
<id property="uid" column="uid"/>
<result property="uname" column="uname"/>
<result column="ubirthday" property="ubirthday"/>
<result column="usex" property="usex"/>
<association property="card" column="uid" javaType="card" select="com.qf.mapper.CardMapper.selectCardByUid"/>
</resultMap>
<select id="selectOneByOneQian" resultMap="selectOneByOneQianQianMap">
select * from `user`
</select>
<!--被嵌套的方法-->
<select id="selectCardByUid" parameterType="int" resultType="card">
select * from card where uid=#{uid}
</select>
2. 嵌套一对多
<!-- 嵌套一对多 -->
<!-- 一对多连接,返回自定义结果集 内要附加 collection-->
<!-- collection “同行内要填” property(实体类内与该表关联的 关系映射属性是哪一个)
column(通过数据库内该表的那个列名 去进行关系映射)
(一对一的要填) javaType(用于说明和那个表相关连)
(嵌套的需要额外加) select(所嵌套方法的全路径“相当于先执行目前的sql命令,
然后再把 column内数据传过去,充当参数,执行下一个sql命令”)
-->
<!-- 嵌套的话 collection “内部”不需要填写内容要填-->
<resultMap id="selectOneByManyQianMap" type="user">
<id property="uid" column="uid"/>
<result property="uname" column="uname"/>
<result column="ubirthday" property="ubirthday"/>
<result column="usex" property="usex"/>
<collection property="orderList" column="uid" ofType="order" select="com.qf.mapper.OrderMapper.selectOrderByUid"/>
</resultMap>
<select id="selectOneByManyQian" resultMap="selectOneByManyQianMap">
select * from `user`
</select>
<!--被嵌套的方法-->
<select id="selectOrderByUid" parameterType="int" resultType="order">
select * from `order` o where o.uid=#{uid}
</select>
七、动态SQL
(一)where-if"…"
<!-- where-if"…" -->
<select id="selectUserByUsexAndUname" resultType="user">
select * from `user`
<where>
<if test="usex != null and usex !=''">
and usex like concat("%",#{usex},"%")
</if>
<if test="uname != null and uname !=''">
and uname like concat("%",#{uname},"%")
</if>
</where>
</select>
(二)where-choose - (when"…" / otherwise)
<!-- where-choose - (when"…" / otherwise) -->
<select id="selectUserByUsexAndUname0" resultType="user">
select * from `user`
<where>
<choose>
<when test="usex != null and usex !=''">
and usex like concat("%",#{usex},"%")
</when>
<when test="uname != null and uname !=''">
and uname like concat("%",#{uname},"%")
</when>
<otherwise>
1=1
</otherwise>
</choose>
</where>
</select>
(三)set-if"…"
<!-- set-if"…" -->
<update id="updateUser" parameterType="user">
update `user`
<set>
<if test="uname != null and uname !=''">
uname=#{uname},
</if>
<if test="ubirthday != null and ubirthday !=''">
ubirthday=#{ubirthday},
</if>
<if test="usex != null and usex !=''">
usex=#{usex},
</if>
</set>
where uid=#{uid}
</update>
(四)trim"…“-if”"
<!-- trim"…"-if"" --> <!-- set-if"…"的进化版 -->
<!-- prefix : 在全部if语句的 前面加上 特定内容-->
<!-- suffix : 在全部if语句的 后面加上 特定内容-->
<!-- prefixOverrides : 在全部if语句的 前面删除 特定内容-->
<!-- suffixOverrides : 在全部if语句的 前面删除 特定内容-->
<update id="updateUser2" parameterType="user">
update `user`
<trim prefix="set" suffixOverrides="," suffix="where uid=#{uid}">
<if test="uname!=null and uname!=''">
uname=#{uname},
</if>
<if test="ubirthday != null and ubirthday !=''">
ubirthday=#{ubirthday},
</if>
<if test="usex != null and usex !=''">
usex=#{usex},
</if>
</trim>
</update>
(五)foreach
1. 多条同时修改
2. 插入方式为Map的时候
<!-- foreach -->
<!--
collection 容器类型 : list、array、map
open 起始符 eg (
close 结束符 eg )
separator 分隔符 eg ,
index 下标号 从0开始,依次递增
item 当前项 任意名称(循环中通过 #{任意名称} 表达式访问)
-->
<insert id="insertManyUser" parameterType="list">
insert into `user`(uname,ubirthday,usex) values
<foreach collection="list" separator="," close=";" item="u">
(#{u.uname},#{u.ubirthday},#{u.usex})
</foreach>
</insert>
<insert id="deleteManyUser" parameterType="list">
delete from `user` where uid in
<foreach collection="list" open="(" separator="," close=")" item="uid">
#{uid}
</foreach>
</insert>
<!-- 多条同时修改-->
<insert id="updateManyUser" parameterType="list">
update `user`
<trim prefix="set" suffixOverrides=",">
<trim prefix="uid = case " suffix="end,">
<foreach collection="list" item="u">
when uid=#{u.uid} then #{u.uid}
</foreach>
</trim>
<trim prefix="uname = case " suffix="end,">
<foreach collection="list" item="u">
when uid=#{u.uid} then #{u.uname}
</foreach>
</trim>
</trim>
where
<foreach collection="list" item="u" separator="or">
uid=#{u.uid}
</foreach>
</insert>
<select id="selectManyUser" parameterType="list" resultType="user">
select * from `user` where
<foreach collection="list" open=" uid in (" close=")" separator="," item="u">
#{u}
</foreach>
</select>
<select id="selectManyUser2" resultType="user">
select * from `user` where
<foreach collection="array" open=" uid in (" close=")" separator="," item="this">
#{this}
</foreach>
</select>
<!-- 插入方式为Map的时候,
其 collection属性值:必须为Map的key值
(此处的key值可以自定义,但调用的时候要输入相对应的自定义key名)
真正要传入用于调用的数据放在value值处
-->
<select id="selectManyUser3" resultType="user">
select * from `user` where
<foreach collection="DiyKey" open="uid in (" close=")" separator="," item="DiyItemName">
#{DiyItemName}
</foreach>
</select>
八、Druid连接池
Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和 SQL 解析器组成。该项目主要是为了扩展 JDBC 的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证、统计 SQL 信息、SQL 性能收集、SQL 注入检查、SQL 翻译等,程序员可以通过定制来实现自己需要的功能。
(一)配置pom.xml
引入Druid依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
(二)创建DruidDataSourceFactory
MyDruidDataSourceFactory并继承PooledDataSourceFactory,并替换数据源。
package com.qf.utils;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
/**
* @author:lyz
* @since: jdk 1.8
**/
public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
public MyDruidDataSourceFactory(){
//替换数据源
this.dataSource = new DruidDataSource();
}
}
(三)修改mybatisConfig.xml
mybatisConfig.xml中连接池相关配置。
<!-- 配置数据库-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<!--<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>-->
<!--更改数据源后,必须按照其特定的 “命名规范name” 来配置相关的配置文件-->
<dataSource type="com.qf.utils.MyDruidDataSourceFactory"><!--数据源工厂-->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
九、缓存(Cache)
内存中的一块存储空间,服务于某个应用程序,旨在将频繁读取的数据临时保存在内存中,便于二次快速访问。
使用场景
:1.数据量比较小 2.数据需要经常使用,不会经常发生改变
3.数据不是特别准确的时候
无缓存:用户在访问相同数据时,需要发起多次对数据库的直接访问,导致产生大量IO、读写硬盘的操作,效率低下 |
---|
![]() |
有缓存:首次访问时,查询数据库,将数据存储到缓存中;再次访问时,直接访问缓存,减少IO、硬盘读写次数、提高效率 |
---|
![]() |
(一)一级缓存
SqlSession级别的缓存,同一个SqlSession的发起多次同构查询,会将数据保存在一级缓存中。
【注意:无需任何配置,默认开启一级缓存】
1. sqlSession.clearCache();
//清空全部数据
/*清空 (当前SqlSession连接的一级缓存) 的全部数据*/
2. sqlSession.commit();
//提交同时清空全部数据
/*提交 (当前SqlSession连接的一级缓存) ,
同时默认 (当前SqlSession连接的一级缓存) 清空全部数据*/
/*
* 缓存:使用情况
* 1.数据量小
* 2.经常使用,但不经常改变
* 3.数据不是特别准确的时候
*
* 一级缓存:
* 1.存取的是对象
* 2.只能用于查询
* 3.增删改会自动提交,然后清空一级缓存内数据
*
* */
(二)二级缓存
SqlSessionFactory级别的缓存,同一个SqlSessionFactory构建的SqlSession发起的多次同构查询,会将数据保存在二级缓存中。
/*
* 二级缓存:
* 当没有 commit时(结束一级缓存),
* 会自动继续调用,一级缓存内的对象
*
* [ 当中间 commit(提交) 清空一级缓存内对象数据时,
* 会通过 Mapper接口(命名空间) 找到对应的二级缓存中获取值,
* 然后再次调用后,也只会从二级缓存中查找 ]
*
* */
1. 配置二级缓存
(1). 修改mybatisConfig.xml
<!-- 开启二级缓存-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--在<typeAliases>标签的上边加上<settings>配置,该工程可以开启二级缓存-->
(2). 修改 对应Bean的Mapper.xml配置文件
<!-- 开启二级缓存的开关-->
<cache/>
具体的查询语句使用二级缓存
(3). 具体的查询语句使用二级缓存
<!-- 针对于具体的查询语句使用二级缓存-->
<select id="selectUserByUidCache" parameterType="int" resultType="user" useCache="true">
select * from `user` u where u.uid=#{uid}
</select>
<!--特定语句内加入 useCache="true" 表示该方法启动二级缓存-->
2. 举例 . 一级缓存
// 一级缓存只能用于查询功能
@Test//实验一级缓存
public void selectUserByUidTest01() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession(true);//自动提交是:当程序全部结束后,才提交(而不是方法结束后提交)
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper1.selectUserByUid(4);//第一次查询后,会将查询获得的对象存储到一级缓存中
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
User user2 = userMapper2.selectUserByUid(4);//没有提交的时候,再次查询,会直接从一级缓存中 查询相应的对象
System.out.println(user1==user2);//true
sqlSession.commit();
}
@Test//实验一级缓存
public void selectUserByUidTest02() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession(false);
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper1.selectUserByUid(4);
//提交: 提交后自动清空一级缓存内数据
sqlSession.commit();
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
User user2 = userMapper2.selectUserByUid(4);
System.out.println(user1==user2);//false
sqlSession.commit();
}
@Test//实验一级缓存
public void insertUserTest01() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession(false);
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper1.selectUserByUid(4);
User user = new User();
user.setUname("神威超人");
user.setUbirthday(LocalDateTime.now());
user.setUsex("男");
int i = userMapper1.insertUser(user);//执行增(删改)操作后:会自动提交数据到数据库,同时自动清空一级缓存内数据
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
User user2 = userMapper2.selectUserByUid(4);
System.out.println(user1==user2);//false
sqlSession.commit();
}
3. 举例 . 二级缓存
@Test//实验二级缓存
public void selectUserByUidCache() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession(false);
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper1.selectUserByUidCache(4);
sqlSession.commit();
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
User user2 = userMapper2.selectUserByUidCache(4);
UserMapper userMapper3 = sqlSession.getMapper(UserMapper.class);
User user3 = userMapper3.selectUserByUidCache(4);
System.out.println(user1==user2);//false , 由于中间 清空一级缓存中的对象数据,所以user1调的是一级缓存的对象数据 user2调用的二级缓存的数据值,所以不是同一对象故==返回值为false
System.out.println(user2==user3);//false , 由于二级缓存存储的是数据值,而==比较引用类型的是地址(是否同一对象),故返回为false
System.out.println(user2.equals(user3));//true , 因为此时两次调用的都是二级缓存中的值,equals比较的也是值,所以返回为true
sqlSession.commit();
}
十、延迟加载(懒加载)
延迟加载:懒加载 ==>谁用谁加载 不是立即进行加载,使用的时候才进行加载【单例设置模式】
使用场景
需求:实现登录功能 => 用户表 ==> 订单表 (一对多的关系)
产生这种场景:使用嵌套查询 在进行登录的时候 会将订单的信息查询出来,
登录的时候 没有必须查询出订单信息,在使用订单表的数据的时候 再查询订单的信息(懒加载) 立即加载:一对一的关系的时候会使用
懒加载:一对多的关系的时候使用懒加载
(一)嵌套一对一的懒加载
1. 修改 对应Bean的Mapper.xml配置文件
<!-- 嵌套一对一懒加载-->
<resultMap id="selectOneToOneQianMap" type="user">
<id property="uid" column="uid"/>
<result property="uname" column="uname"/>
<result property="ubirthday" column="ubirthday"/>
<result property="usex" column="usex"/>
<association property="card" column="uid" javaType="card"
select="com.qf.mapper.CardMapper.selectCardByUid" fetchType="lazy" />
</resultMap>
<select id="selectOneToOneQian" resultMap="selectOneToOneQianMap">
select * from `user`
</select>
<!--在 "嵌套一对一" 的基础上,给association加上一个 fetchType="lazy" 属性-->
2. 测试 用到其数据的时候才会执行sql语句
// 嵌套一对一的懒加载
@Test
public void selectOneToOneQian() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession(false);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.selectOneToOneQian();
userList.forEach(user -> {
System.out.println(user.getUname());
if (user.getCard()!=null){
System.out.println(user.getCard().getCnumid());
}
});
}
(二)嵌套一对多的懒加载
1. 修改 对应Bean的Mapper.xml配置文件
<!-- 嵌套一对多懒加载-->
<resultMap id="selectOneToManyQianMap" type="user">
<id property="uid" column="uid"/>
<result property="uname" column="uname"/>
<result property="ubirthday" column="ubirthday"/>
<result property="usex" column="usex"/>
<collection property="orderList" column="uid" ofType="list"
select="com.qf.mapper.OrderMapper.selectOrderByUid" fetchType="lazy"/>
</resultMap>
<select id="selectOneToManyQian" resultMap="selectOneToManyQianMap">
select * from `user`
</select>
<!--在 "嵌套一对多" 的基础上,collection fetchType="lazy" 属性-->
// 嵌套一对多的懒加载
@Test
public void selectOneToManyQian() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession(false);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.selectOneToManyQian();
userList.forEach(user -> {
System.out.println(user.getUname());
List<Order> orderList = user.getOrderList();
if (orderList.size()>0){
orderList.forEach(order -> System.out.println(order));
}
});
}
十一、PageHelper(分页插件)
PageHelper是适用于MyBatis框架的一个分页插件,使用方式极为便捷,支持任何复杂的单表、多表分页查询操作。
- 访问与下载
- 官方网站:https://pagehelper.github.io/
- 下载地址:https://github.com/pagehelper/Mybatis-PageHelper
- 开发步骤
- PageHelper中提供了多个分页操作的静态方法入口。
(一)配置
1. 修改pom.xml 引入依赖
引入依赖pom.xml中引入PageHelper依赖。
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
2.修改mybatisConfig.xml
<!-- 配置PackHelper分页插件-->
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<!--在<typeAliases>标签的下方,加上<plugins>配置,该工程使用…插件-->
(二)测试分页插件PageHelper
// 测试分页插件PageHelper
@Test
public void selectAllUserTestPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession(false);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
/*
* 设置分页:
* 第一个参数:pageNum:当前页
* 第二个参数:pageSize:每页展示最大数
*/
PageHelper.startPage(1,3);
List<User> userList = userMapper.selectAllUserTestPaPageHelper();
/* 实例化PageInfo 同时把要分页展示的数据传入 */
PageInfo<User> pageInfo=new PageInfo<>(userList);
System.out.println(pageInfo.toString());
}
(三)常用的PageInfo
属性名 描述 pageNum 当前页 pageSize 页量 total 总记录数 pages 总页数 list 集合(数据)
(四)注意事项
- 只有在PageHelper.startPage()方法之后的第一个查询会有执行分页。
- 分页插件不支持带有“for update”的查询语句。
- 分页插件不支持“嵌套查询”,由于嵌套结果方式会导致结果集被折叠,所以无法保证分页结果数量正确。。
十二、MyBatis注解操作
通过在接口中直接添加MyBatis注解,完成CRUD。
- 注意:接口注解定义完毕后,需将接口全限定名注册到mybatis-config.xml的< mappers >中。
- 经验:注解模式属于硬编码到.java文件中,失去了使用配置文件外部修改的优势,可结合需求选用。
(一)修改mybatisConfig.xml
<mappers>
<!--<mapper resource="com/qf/mapper/UserMapper.xml"/>
<mapper resource="com/qf/mapper/CardMapper.xml"/>
<mapper resource="com/qf/mapper/OrderMapper.xml"/>-->
<package name="com.qf.mapper"/>
</mappers>
<!--使用<package>方式直接将工程下包内,的全部持久层接口类都配置号映射关系-->
<!--也可以用<mapper class="……"> 和package一样的效果-->
(二)测试
持久层接口类 - 模版
package com.qf.mapper; import com.qf.entity.Card; import com.qf.entity.User; import org.apache.ibatis.annotations.*; import org.apache.ibatis.mapping.FetchType; import java.util.List; /** * @author:lyz * @since: jdk 1.8 **/ public interface UserMapper { //……………… }
测试类
package com.qf.test; import com.qf.entity.User; import com.qf.mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.time.LocalDateTime; import java.util.List; /** * @author:lyz * @since: jdk 1.8 **/ public class MyTest { private SqlSession sqlSession = null; public SqlSession getSqlSession() { if (sqlSession == null) { try { sqlSession = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatisConfig.xml")).openSession(true); } catch (IOException e) { e.printStackTrace(); } } return sqlSession; } }
1. 简单的增删改查
(1). 持久层接口类
@Insert("insert into `user` (uname,ubirthday,usex)values(#{uname},#{ubirthday},#{usex})")
int insertUser(User user);
@Delete("delete from `user` where uid=#{uid}")
int deleteUserByUid(@Param("uid")int uid);
@Update("update `user` set uname=#{uname},ubirthday=#{ubirthday},usex=#{usex} where uid=#{uid}")
int updateUserByUid(User user);
@Select("select * from `user` where uid=#{uid}")
User selectUserByUid(@Param("uid")int uid);
(2). 测试类
@Test
public void insertUser() {
User user = new User();
user.setUname("TempInsert");
user.setUbirthday(LocalDateTime.now());
user.setUsex("男");
int i = getSqlSession().getMapper(UserMapper.class).insertUser(user);
System.out.println(i);
}
@Test
public void deleteUserByUid() {
int i = getSqlSession().getMapper(UserMapper.class).deleteUserByUid(12);
System.out.println(i);
}
@Test
public void updateUserByUid() {
User user = new User();
user.setUid(14);
user.setUname("TempUpdate");
user.setUbirthday(LocalDateTime.now());
user.setUsex("女");
int i = getSqlSession().getMapper(UserMapper.class).updateUserByUid(user);
System.out.println(i);
}
@Test
public void selectUserByUid() {
User user = getSqlSession().getMapper(UserMapper.class).selectUserByUid(14);
System.out.println(user);
}
2. 嵌套一对一
(1). 持久层接口类
/* 嵌套一对一
1.(最后一个)连接的 @Result 配置内容:
1.1. property 实体类中用于嵌套的属性名
1.2. column 在数据库中两个表,是关于那个列名相关联起来的
1.3. javaType 返回的数据类型
(tips:若返回为数组则是List.class类型,
若返回为其他实体类则是 实体类.class)
1.4. one 要配置 @One
1.4.1 @One 必须配置 select=""
填被嵌套方法的全路径 eg: com.qf.mapper.CardMapper.selectByUid
选择性配置 fetchType=
加载模式(默认/懒加载/立即加载)eg:FetchType.LAZY(懒加载)
*/
@Select("select * from `user`")
@Results({
@Result(id=true,property = "uid",column = "uid"),
@Result(property = "uname",column = "uname"),
@Result(property = "ubirthday",column = "ubirthday"),
@Result(property = "usex",column = "usex"),
@Result(property = "card",column = "uid",javaType = Card.class,
one = @One(
select = "com.qf.mapper.CardMapper.selectByUid",fetchType = FetchType.LAZY
))
})
List<User> selectOneToOneQian();
(2). 测试类
@Test
public void selectOneToOneQian() {
List<User> userList = getSqlSession().getMapper(UserMapper.class).selectOneToOneQian();
userList.forEach(user -> {
System.out.println(user.getUname());
if (user.getCard()!=null){
System.out.println(user.getCard().getCnumid());
}
});
}
3. 嵌套一对多
(1). 持久层接口类
/* 嵌套一对多
1.(最后一个)连接的 @Result 配置内容:
1.1. property 实体类中用于嵌套的属性名
1.2. column 在数据库中两个表,是关于那个列名相关联起来的
1.3. javaType 返回的数据类型
(tips:若返回为数组则是List.class类型,
若返回为其他实体类则是 实体类.class)
1.4. many 要配置 @Many
1.4.1 @Many 必须配置 select=""
填被嵌套方法的全路径 eg: com.qf.mapper.CardMapper.selectByUid
选择性配置 fetchType=
加载模式(默认/懒加载/立即加载)eg:FetchType.LAZY(懒加载)
*/
@Select("select * from `user`")
@Results({
@Result(id = true,property = "uid",column = "uid"),
@Result(property = "uname",column = "uname"),
@Result(property = "ubirthday",column = "ubirthday"),
@Result(property = "usex",column = "usex"),
@Result(property = "orderList",column = "uid",javaType = List.class,
many = @Many(
select = "com.qf.mapper.OrderMapper.selectOrderByUid",fetchType = FetchType.LAZY
))
})
List<User> selectOneToManyQian();
(2). 测试类
@Test
public void selectOneToManyQian() {
List<User> userList = getSqlSession().getMapper(UserMapper.class).selectOneToManyQian();
userList.forEach(user -> {
System.out.println(user.getUname());
if (user.getOrderList().size()>0){
user.getOrderList().forEach(order -> {
System.out.println(order.getOname());
});
}
});
}
十三、MyBatis的逆向工程
自动生成数据库中“表”的“实体类”,及简单的“增删改查”功能
(一)配置
1. 修改mybatisConfig.xml
<!-- 配置 MyBatis的逆向工程 依赖包-->
<properties>
<mybatis.version>3.5.6</mybatis.version>
<mysql-connector-java.version>8.0.17</mysql-connector-java.version>
<mybatis-generator-maven-plugin.version>1.3.2</mybatis-generator-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
</dependencies>
<!-- 配置 MyBatis的逆向工程 插件-->
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>${mybatis-generator-maven-plugin.version}</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
<!--这里其实可配置多个插件,eg:PackHelper分页插件-->
<!--<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>-->
</plugins>
</build>
<!--在<typeAliases>标签的下方,加上<plugins>配置,该工程使用…插件-->
2. 添加配置文件generator.properties
- jdbc.driverLocation = 本地mysql-connector-java-****.jar 的全路径
- jdbc.driverClass = com.mysql.cj.jdbc.Driver(版本8以上)
- com.mysql.jdbc.Driver(版本8以下)
- jdbc.connectionURL = jdbc:mysql:///数据库名称?serverTimezone=Asia/Shanghai(版本8以上)
- jdbc:mysql://localhost:3306/数据库名称(版本8以下)
- 不写localhost:3306 默认本地service
- jdbc.userId = mysql用户名
- jdbc.password = mysql密码
jdbc.driverLocation=C:\\Users\\lyz\\.m2\\repository\\mysql\\mysql-connector-java\\8.0.17\\mysql-connector-java-8.0.17.jar
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.connectionURL=jdbc:mysql:///mybatis_03?serverTimezone=Asia/Shanghai
jdbc.userId=root
jdbc.password=root
3. 添加配置文件 generatorConfig.xml
javaModelGenerator 修改该标签的 targetPackage属性为要自定义要生成的文件路径
sqlMapGenerator 修改该标签的 targetPackage属性为要自定义要生成的文件路径
javaClientGenerator 修改该标签的 targetPackage属性为要自定义要生成的文件路径
添加要生成数据库中的表单,的特定配置信息
- tableName :数据库中表单的名称
- domainObjectName :该表单生成的实体类名称
<table tableName="user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> </table>
<?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="generator.properties"></properties>
<!--指定特定数据库的jdbc驱动jar包的位置-->
<classPathEntry location="${jdbc.driverLocation}"/>
<context id="default" targetRuntime="MyBatis3">
<!-- optional,旨在创建class时,对注释进行控制 -->
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--jdbc的数据库连接 -->
<!--Mysql版本8 以上的要而外配置<property name="nullCatalogMeansCurrent" value="true"/>
Mysql版本8 以下的则不需要这条属性-->
<jdbcConnection
driverClass="${jdbc.driverClass}"
connectionURL="${jdbc.connectionURL}"
userId="${jdbc.userId}"
password="${jdbc.password}">
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制-->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
targetPackage 指定生成的model生成所在的包名
targetProject 指定在该项目下所在的路径
-->
<javaModelGenerator targetPackage="com.qf.entity"
targetProject="src/main/java">
<!-- 是否允许子包,即targetPackage.schemaName.tableName -->
<property name="enableSubPackages" value="false"/>
<!-- 是否对model添加 构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 是否对类CHAR类型的列的数据进行trim操作 -->
<property name="trimStrings" value="true"/>
<!-- 建立的Model对象是否 不可改变 即生成的Model对象不会有 setter方法,只有构造方法 -->
<property name="immutable" value="false"/>
</javaModelGenerator>
<!--Mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
<sqlMapGenerator targetPackage="com.qf.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口
-->
<javaClientGenerator targetPackage="com.qf.mapper"
targetProject="src/main/java" type="XMLMAPPER">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<table tableName="user" domainObjectName="User"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false">
</table>
<table tableName="card" domainObjectName="Card"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false">
</table>
</context>
</generatorConfiguration>