1.Mybatis的使用
引入依赖
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
1.mybatis-config.xml主配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
mybatis中核心配置文件中标签的顺序
(properties?,settings?,typeAliases?,typeHandlers?,
objectFactory?,objectWrapperFactory?,reflectorFactory?,
plugins?,environments?,databaseIdProvider?,mappers?)"
-->
<!--引入properties文件-->
<properties resource="jdbc.properties"/>
<!--设置类别名-->
<typeAliases>
<!--alias别名名称 不写:默认类名user或者User都可以-->
<!-- <typeAlias type="com.wyr.pojo.User" alias="user"/>-->
<!--以包为单位,将包下所有的类型设置默认的类型别名 即类名且不区分大小写-->
<package name="com.wyr.pojo"/>
</typeAliases>
<!--
environments
environments:配置多个连接数据库的环境
属性:
default:设置默认使用的环境的id
-->
<environments default="mysql">
<!--
environment :配置某个具体的环境
属性:
id:表示连接数据库环境的唯一标识,不能重复
-->
<environment id="mysql">
<!--
transactionManager:设置事务管理方式
属性:
type="JDBC|MANAGED"
JDBC:表示当前环境中,执行sql时,使用的是JDBC中原生的事务管理方式,事务的提交或者回滚需要手动处理
MANAGED:被管理(例如spring)
-->
<transactionManager type="JDBC"/>
<!--
dataSource :设置数据源
属性:
type:设置数据源的类型
type="POOLED|UNPOOLED|JNDI"
POOLED:表示使用数据库连接池缓存数据库连接
UNPOOLED:表示不使用数据库连接池
JNDI:表示使用上下文中的数据源
-->
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<!-- <mapper resource="mappers/UserMapper.xml"/>-->
<!--
前置小知识:mapper映射文件现在都在resource文件夹下
如何在resource下创建多级包(文件夹):
可以 new - Directory - com/xxx/xxx/mapper
以包为单位引入映射文件
要求:
1.mapper接口所在的包要和映射文件所在的包一致
2.mapper接口和映射文件的名字一致
-->
<package name="com.wyr.mapper"/>
</mappers>
</configuration>
2.创建模板文件
2.Mybatis获取参数的两种方式
${} 本质字符串拼接
#{}本质占位符赋值
1.Mybatis获取参数值的各种情况:
1.mapper接口方法的参数为单个字面量类型
可以通过${}和#{}以任意的名称获取参数,但是需要注意${} 的单引号问题
select * from user where username = '${username}'
或
select * from user where username = #{username}
2.mapper接口方法的参数为多个时
此时Mybatis会将这些参数放在一个map集合中,以两种方式进行存储
a>以arg0,arg1…为键,以参数为值
b>以param1,param2…为键,以参数为值 因此只需要通过#{}或者 以键的方式访问值即可,但是需要注意 {}以键的方式访问值即可,但是需要注意 以键的方式访问值即可,但是需要注意{}的单引号问题
<!--User getUserLogin(String username,int password);-->
select * from user where username= #{param1} and password =#{param2}
3.mapper接口方法的参数有多个时,可以手动将这些参数放在一个map集合中存储
只要通过#{}和 以键(自定义键)的方式访问值即可,但是需要注意 {}以键(自定义键)的方式访问值即可,但是需要注意 以键(自定义键)的方式访问值即可,但是需要注意{}的单引号问题
Map<String,Object> map = new HashMap<String,Object>();
map.put("password",123);
map.put("username","www");
<!--User getUserLogin(Map<String,Object> user);-->
<select id="getUserLogin1" resultType="user" parameterType="map">
select * from user where username= #{username} and password =#{password}
</select>
4.mapper接口的参数是实体类类型的参数
只要通过#{}和 以属性的方式访问属性值即可,但是需要注意 {}以属性的方式访问属性值即可,但是需要注意 以属性的方式访问属性值即可,但是需要注意{}的单引号问题
5.使用@Param注解命名参数(接受多个参数)
此时Mybatis会将这些参数放在一个map集合中,会以两种方式存储
1.以@param注解的值为键,以参数为值
2.以param1,param2…为键,以参数为值
因此只需要通过#{}和
以键的方式访问值以可,但是需要注意
{}以键的方式访问值以可,但是需要注意
以键的方式访问值以可,但是需要注意{}的单引号问题
属性:有set,get方法的变量
6.mybatis中设置了默认的类型别名
3.mybatis查询功能之方法放回值
1.根据id查询用户信息为一个map集合
<!-- Map<String,Object> getUserByIdToMap(@Param("id") String id);-->
<select id="getUserByIdToMap" resultType="map">
select * from user where id= #{id}
</select>
2.查询所有用户信息为一个map集合的方式
<!--List<Map<String,Object>> getUsersToMap();-->
<select id="getUsersToMap" resultType="map">
select * from USER ;
</select>
<!--
@MapKey("id") 将查询出的id的值作为键,将查询出来的每条map结果作为值,放在同一个map集合
Map<String,Object> getUsersToMaps();
-->
<select id="getUsersToMaps" resultType="map">
select * from user
</select>
4.特殊sql的执行
(1). mybatis处理模糊查询
<!-- List<User> getUsersByLikeName(@Param("username") String username);-->
<select id="getUsersByLikeName" resultType="user">
select * from user where username like '%${username}%'或者
select * from user where username like '%'#{username}'%'
</select>
<select id="getUsersByLikeName" resultType="user">
select * from user where username like concat('%',#{username},'%')
</select>
(2).批量删除(不用)
<!--Integer deleteMore(String ids);-->
<delete id="deleteMore" parameterType="string">
delete from user where id in (${ids})
</delete>
(3).mybatis动态设置表名
<!--List<User> getUserByTableName(@Param("tableName") String tableName);-->
<select id="getUserByTableName" parameterType="string" resultType="user">
select * from ${tableName}
</select>
(4).添加功能获取自增的主键
<!--
useGeneratedKeys:user表是否使用了自动递增的主键
keyProperty="id":增删改方法返回值固定(受影响的行数)
所以只能把返回的值放到参数对象user的id属性上
-->
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
insert into user values (null,#{username},#{password})
</insert>
5.解决字段名和属性名不一致的情况
- 为字段起别名,保持和类中属性名一致
- mybatis-config.xml全局配置文件中,将数据库字段中_自动映射为驼峰
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
- 通过resultmap实现自定义映射关系(类中属性和表中字段的映射)
(同名的也要写)
<resultMap id="EmpMap" type="emp">
<!--id:设置主键 result设置普通字段-->
<id property="eno" column="eno"></id>
<result property="eName" column="e_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<!--List<Emp> getAllEmps();-->
<select id="getAllEmps" resultMap="EmpMap">
select * from t_emp;
</select>
(1)处理多对一的映射关系解决方法
1. 通过级联属性解决多对一的映射关系涉及两个类
<!-- Emp getEmpById(Integer empId);-->
<resultMap id="EmpAndDeptOne" type="emp">
<id property="eno" column="eno"></id>
<result property="eName" column="e_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<result property="dept.deptNo" column="dept_no"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<select id="getEmpById" resultMap="EmpAndDeptOne" >
select * from t_emp
left join t_dept on t_emp.did= t_dept.dept_no
where t_emp.eno = #{empId}
</select>
2.通过association 解决多对一的映射
<resultMap id="EmpAndDeptTwo" type="emp">
<id property="eno" column="eno"></id>
<result property="eName" column="e_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<!--
association:处理多对一的映射关系
property:处理多对-的映射关系的属性名
javaType:属性类型
-->
<association property="dept" javaType="Dept">
<id property="deptNo" column="dept_no"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
<select id="getEmpById" resultMap="EmpAndDeptTwo" >
select * from t_emp
left join t_dept on t_emp.did= t_dept.dept_no
where t_emp.eno = #{empId}
</select>
3.通过分步查询解决多对一的映射关系
<!--
select:设置分布查询的sql的唯一标识(namespace.sqlId 或者mapper接口的全类名.方法名)
column:设置查询条件
property:多对一映射关系的类中属性
全局延迟加载:
<setting name="lazyLoadingEnabled" value="true"/>
fetchType:当开启了全局的延迟加载后,可通过此属性手动控制延迟加载的效果
fetchType="lazy|egger":lazy表示延迟加载(默认),egger表示立即加载
-->
<association property="dept"
column="did"
select="com.wyr.mapper.DeptMapper.getDeptById"
fetchType="eager"
>
</association>
</resultMap>
<!-- Emp getEmpAndDeptByStep(@Param("eId") Integer empId);-->
<select id="getEmpAndDeptByStep" parameterType="int" resultMap="empAndDeptByStepResultMap">
select * from t_emp where eno= #{eId}
</select>
<!-- Dept getDeptById(@Param("dId") Integer deptId);-->
<select id="getDeptById" parameterType="int" resultType="Dept">
select * from t_dept where dept_no = #{dId}
</select>
4.延迟加载与(分布查询相关)
与3相关
lazyLoadingEnabled:实现按需加载如果只需要员工姓名则只执行emp的sql语句
如果需要emp中所有属性(包括dept)则是查询emp和dept
(2)处理一对多的映射关系的解决方法
1.通过.collection解决一对多的映射关系
<resultMap id="DeptAndEmpResultMap" type="Dept">
<id column="dept_no" property="deptNo"></id>
<result column="dept_name" property="deptName"></result>
<!--
collection:解决一对多的映射关系
property:Dept类的属性
ofType:集合中数据类型
-->
<collection property="emps" ofType="Emp">
<id property="eno" column="eno"></id>
<result property="eName" column="e_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>
<!-- Dept getDeptAndEmpByDeptId(@Param("dId") Integer deptId);-->
<select id="getDeptAndEmpByDeptId" resultMap="DeptAndEmpResultMap" parameterType="int">
SELECT * FROM t_dept
LEFT JOIN t_emp
ON t_dept.dept_no = t_emp.did
WHERE t_dept.dept_no = #{dId}
</select>
2.通过分布查询解决一对多的映射关系
<resultMap id="deptAndEmpByDeptIdStepResultMap" type="Dept">
<id column="dept_no" property="deptNo"></id>
<result column="dept_name" property="deptName"></result>
<!--
collection:处理一对多的映射关系
select:分布查询sql语句的唯一标识
column:查询条件(dept表中字段)
全局延迟加载:
<setting name="lazyLoadingEnabled" value="true"/>
fetchType:当开启了全局的延迟加载后,可通过此属性手动控制延迟加载的效果
fetchType="lazy|egger":lazy表示延迟加载(默认),egger表示立即加载
-->
<collection property="emps"
select="com.wyr.mapper.EmpMapper.getEmpsByDeptId"
column="dept_no"
fetchType="lazy"
>
</collection>
</resultMap>
<!-- Dept getDeptAndEmpByDeptIdStep(@Param("dId") Integer deptId);-->
<select id="getDeptAndEmpByDeptIdStep" resultMap="deptAndEmpByDeptIdStepResultMap" parameterType="int">
select * from t_dept where dept_no = #{dId}
</select>
6.动态sql
本质:一系列标签
功能:帮我们动态拼接sql语句
(1)if
根据标签中test属性所对应的表达式决定标签中的内容是否需要拼接到sql中
<!-- List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" parameterType="Emp" resultType="Emp">
select * from t_emp where 1=1
<!-- test eName类中属性-->
<if test="eName!=null and eName!=''">
e_name = #{eName}
</if>
<if test="age!=null and age!=''">
and age =#{age}
</if>
<if test="sex!=null and sex!=''">
and sex =#{sex}
</if>
</select>
(2) where
<!-- List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" parameterType="Emp" resultType="Emp">
select * from t_emp
<!--
1. 当where标签中有内容时,会自动生成where关键字
去掉内容前多余的and或者or(当ename=null或者ename="")
2. 当where标签没有内容时(所有条件不成立),此时where标签没有任何作用
3. where 标签不能去掉内容后多余的and或者or
select * from t_emp WHERE age =? and
-->
<where>
<if test="eName!=null and eName!=''">
e_name = #{eName}
</if>
<if test="age!=null and age!=''">
and age =#{age}
</if>
<if test="sex!=null and sex!=''">
and sex =#{sex}
</if>
</where>
</select>
(3) trim=where增强
<!-- List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" parameterType="Emp" resultType="Emp">
select * from t_emp
<!--
若trim标签中有内容时:
1. prefix|suffix:将trim标签中内容前或者后面添加指定内容
2. suffixOverrides|prefixOverrides:将trim标签中内容前面或者后面去掉指定内容
若trim标签中没有内容
trim标签没有任何效果
-->
<trim prefix="where" suffixOverrides="and">
<if test="eName!=null and eName!=''">
e_name = #{eName} and
</if>
<if test="age!=null and age!=''">
age =#{age} and
</if>
<if test="sex!=null and sex!=''">
sex =#{sex}
</if>
</trim>
</select>
(4)choose when otherwise 相等于 if elseif’…else
choose 是父标签
if…elseif…elseif=when
else=otherwise
when至少有一个
otherwise至多一个
<select id="getEmpByCondition" parameterType="Emp" resultType="Emp">
select * from t_emp
<where>
<!-- 只有一个条件最终成立 -->
<choose>
<when test="eName!=null and eName!=''">
e_name = #{eName}
</when>
<when test="age!=null and age!=''">
age = #{age}
</when>
<when test="sex!=null and sex!=''">
sex = #{sex}
</when>
<otherwise>
did = 1
</otherwise>
</choose>
</where>
</select>
(5)foreach
- collection:设置需要循环的数组或者集合
- item:标识数组或者集合中的每一个数据
- separator:循环体之间的分隔符
- open:foreach标签所循环的所有内容的开始符
- close:foreach标签所循环的所有内容的结束符
<!-- Integer deleteMoreByArray(@Param("eids") Integer[]eids);-->
<select id="deleteMoreByArray" parameterType="int">
<!-- 批量删除方式一-->
delete from t_emp where eno in
<foreach collection="eids" item="eid" open="(" close=")" separator=",">
#{eid}
</foreach>
<!-- 批量删除方式二-->
delete from t_emp where
<foreach collection="eids" item="eid" separator="or">
eno = #{eid}
</foreach>
</select>
<!--
批量添加
Integer insertMoreByList(@Param("empList") List<Emp> empList);
-->
<insert id="insertMoreByList" parameterType="emp">
insert into t_emp
values
<foreach collection="empList" item="emp" separator=",">
(null,#{emp.eName},#{emp.age},#{emp.sex},#{emp.email},null)
</foreach>
</insert>
(6)sql
<!-- 设置sql片段-->
<sql id="empColumns">
eno,e_name,sex,age,email
</sql>
<!-- 引用sql片段-->
select <include refid="empColumns"></include> from t_emp
7.Mybatis的缓存
(1)一级缓存
一级缓存默认是开启的,缓存针对的是查询数据
手动清空缓存:sqlSession.clearCache();
(2)二级缓存
1.二级缓存的相关配置
(3)缓存查询的顺序
(4)整合第三方缓存EHCache
- 引入依赖
<!--Mybatis EHCache整合包-->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<!--slf4j日志门面的一个具体实现-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
3. 创建EHCache的配置文件ehcache.xml
名字必须叫ehcache.xml
<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="D:\atguigu\ehcache"/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
- 设置二级缓存的类型
在xxxMapper.xml文件中设置二级缓存类型
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
- 加入logback日志
存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。
创建logback的配置文件logback.xml,名字固定,不可改变
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 指定日志输出的位置 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志输出的格式 -->
<!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
</encoder>
</appender>
<!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
<!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
<root level="DEBUG">
<!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
<appender-ref ref="STDOUT" />
</root>
<!-- 根据特殊需求指定局部日志级别 -->
<logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
</configuration>
属性名 | 是否必须 | 作用 |
---|---|---|
maxElementsInMemory | 是 | 在内存中缓存的element的最大数目 |
maxElementsOnDisk | 是 | 在磁盘上缓存的element的最大数目,若是0表示无穷大 |
eternal | 是 | 设定缓存的elements是否永远不过期。 如果为true,则缓存的数据始终有效, 如果为false那么还要根据timeToIdleSeconds、timeToLiveSeconds判断 |
overflowToDisk | 是 | 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上 |
timeToIdleSeconds | 否 | 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时, 这些数据便会删除,默认值是0,也就是可闲置时间无穷大 |
timeToLiveSeconds | 否 | 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大 |
iskSpoolBufferSizeMB | 否 | DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区 |
diskPersistent | 否 | 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false |
diskExpiryThreadIntervalSeconds | 否 | 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s, 相应的线程会进行一次EhCache中数据的清理工作 |
memoryStoreEvictionPolicy | 否 | 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。 默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出) |
8.mybatis逆向工程=》自动生成实体类mapper…
- 正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的
- 逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:
Java实体类
Mapper接口
Mapper映射文件
(1) 创建逆向工程的步骤之清晰简洁版
1. 添加依赖和插件
<dependencies>
<!-- MyBatis核心依赖包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<!-- 控制Maven在构建过程中相关配置 -->
<build>
<!-- 构建过程中用到的插件 -->
<plugins>
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
2.创建逆向工程的配置文件
- 文件名必须是:generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版)
MyBatis3: 生成带条件的CRUD(奢华尊享版)
-->
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<!-- 为了防止生成的代码中有很多注释,比较难看,加入下面的配置控制 -->
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<commentGenerator>
<!-- 去掉 generator默认生成的所有注解 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 数据库的连接信息 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/demo"
userId="root"
password="root">
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.wyr.pojo" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="com.wyr.mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.wyr.mapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 逆向分析的表 -->
<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
<!-- domainObjectName属性指定生成出来的实体类的类名 -->
<table tableName="t_emp" domainObjectName="Emp"/>
<table tableName="t_dept" domainObjectName="Dept"/>
</context>
</generatorConfiguration>
3. 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中核心配置文件中标签的顺序
(properties?,settings?,typeAliases?,typeHandlers?,
objectFactory?,objectWrapperFactory?,reflectorFactory?,
plugins?,environments?,databaseIdProvider?,mappers?)"
-->
<!--引入properties文件-->
<properties resource="jdbc.properties"/>
<settings>
<!--类中属性驼峰和表中带_的字段之间的映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启懒加载与分布查询有关-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
<!--设置类别名-->
<typeAliases>
<!--alias别名名称 不写:默认类名user或者User都可以-->
<!-- <typeAlias type="com.wyr.pojo.User" alias="user"/>-->
<!--以包为单位,将包下所有的类型设置默认的类型别名 即类名且不区分大小写-->
<package name="com.wyr.pojo"/>
</typeAliases>
<!--
environments
environments:配置多个连接数据库的环境
属性:
default:设置默认使用的环境的id
-->
<environments default="mysql">
<!--
environment :配置某个具体的环境
属性:
id:表示连接数据库环境的唯一标识,不能重复
-->
<environment id="mysql">
<!--
transactionManager:设置事务管理方式
属性:
type="JDBC|MANAGED"
JDBC:表示当前环境中,执行sql时,使用的是JDBC中原生的事务管理方式,事务的提交或者回滚需要手动处理
MANAGED:被管理(例如spring)
-->
<transactionManager type="JDBC"/>
<!--
dataSource :设置数据源
属性:
type:设置数据源的类型
type="POOLED|UNPOOLED|JNDI"
POOLED:表示使用数据库连接池缓存数据库连接
UNPOOLED:表示不使用数据库连接池
JNDI:表示使用上下文中的数据源
-->
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<!-- <mapper resource="mappers/UserMapper.xml"/>-->
<!--
前置小知识:mapper映射文件现在都在resource文件夹下
如何在resource下创建多级包(文件夹):
可以 new - Directory - com/xxx/xxx/mapper
以包为单位引入映射文件
要求:
1.mapper接口所在的包要和映射文件所在的包一致
2.mapper接口和映射文件的名字一致
-->
<package name="com.wyr.mapper"/>
</mappers>
</configuration>
4.运行程序生成对应文件
(2)复杂版本的使用
与简洁版相似 只需要将创建逆向工程的配置文件中 targetRuntime="MyBatis3Simple"改为
targetRuntime="MyBatis3"即可
相比较简洁版简单的增删查改,复杂版提供了更多的功能
1.QBC
- 查
- selectByExample:按条件查询,需要传入一个example对象或者null;如果传入一个null,则表示没有条件,也就是查询所有数据
- example.createCriteria().xxx:创建条件对象,通过andXXX方法为SQL添加查询添加,每个条件之间是and关系
- example.or().xxx:将之前添加的条件通过or拼接其他条件
@Test
public void test(){
try {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//查询所有员工
List<Emp> emps1 = empMapper.selectByExample(null);
System.out.println(emps1);
//条件查询 根据(eName = '张三' age>=20) or( did!=null)
EmpExample empExample = new EmpExample();
empExample.createCriteria().andENameEqualTo("张三").andAgeGreaterThanOrEqualTo(20);
empExample.or().andDidIsNotNull();
List<Emp> emps2 = empMapper.selectByExample(empExample);
System.out.println(emps2);
} catch (IOException e) {
e.printStackTrace();
}
}
2.修改
(1).updateByPrimaryKey:通过主键进行数据修改,如果某一个值为null,也会将对应的字段改为null
empMapper.updateByPrimaryKey(new Emp(1,"wy",null,null,null,null));
(2).updateByPrimaryKeySelective():通过主键进行选择性数据修改,如果某个值为null,则不修改这个字段
empMapper.updateByPrimaryKeySelective(new Emp(3,"wyt",null,null,null,null));
9.分页插件
1.添加依赖
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
2.在MyBatis的核心配置文件(mybatis-config.xml)中配置插件
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3.使用插件的分页功能
使用MyBatis的分页插件实现分页功能:
1、需要在查询功能之前开启分页
PageHelper.startPage(int pageNum,int pagesize);
2、在查询功能之后获取分页相关信息
PageInfo page = new PageInfo<>(List, 5);
List表示分页数据
5标识当前分页的个数
(1)方式一(使用page)
代码:
@Test
public void test(){
try {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//简单获取到分页数据
Page<Emp> page = PageHelper.startPage(1, 3);
List<Emp> empList = empMapper.selectByExample(null);
System.out.println(page);
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
(2)方式二:使用pageInfo(关于分页的信息更加详细)
@Test
public void test(){
try {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
/*以下均为分页相关代码*/
PageHelper.startPage(1, 3);
//查询所有员工信息
List<Emp> empList = empMapper.selectByExample(null);
PageInfo<Emp> pageInfo = new PageInfo<>(empList,5);
System.out.println(pageInfo);
} catch (IOException e) {
e.printStackTrace();
}
}
结果
(3)1和2结果数据含义
pageNum:当前页的页码
pageSize:每页显示的条数
size:当前页显示的真实条数
total:总记录数
pages:总页数
prePage:上一页的页码
nextPage:下一页的页码
isFirstPage/isLastPage:是否为第一页/最后一页
hasPreviousPage/hasNextPage:是否存在上一页/下一页
navigatePages:导航分页的页码数
navigatepageNums:导航分页的页码,[1,2,3,4,5]