mybatis基础项目依赖
mybatis、mysql驱动、junit、防止资源导入失败
扩展:log4j、lombok、分页插件
XML
<!-- Mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- Mysql连接依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
资源导出问题解决
XML
<!--在build中配置resources, 来防止我们资源导出失败问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
log4j.properties文件设置
XML
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/serenity.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
lombok常用:@Data、@AllArgsConstructor、@NoArgsConstructor
mybatis-config.xml配置文件
包括日志、驼峰命名、别名、环境连接、绑定Mapper配置文件,二级缓存、分页插件等基础配置。
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>
<!-- Load external configuration files-->
<properties resource="db.properties"/>
<settings>
<!--Set up a default logging factory-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!--Set up camelCase naming mapping-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--Enable global configuration caching-->
<setting name="cacheEnabled" value="true"/>
</settings>
<typeAliases>
<!--<typeAlias type="com.User" alias="User"/>-->
<package name="com.serenity.pojo"/>
</typeAliases>
<!--setting limit page-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!--binding on interface-->
<mappers>
<mapper class="com.serenity.dao.TeacherMapper"/>
<mapper class="com.serenity.dao.StudentMapper"/>
</mappers>
</configuration>
db.propertise数据库文件
XML
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatistest?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username=root
password=123456
Mapper映射文件的头文件
通过resultMap实现数据库列名和属性值一一对应(使用列和属性都写)。
- resultMap中的id:唯一标识,不能重复
- type:映射的类型。
- id标签:设置主键的映射关系
- result:设置普通字段的映射关系
- property:设置的是映射关系中的属性名,必须是type属性所设置的实体类类型中的属性。
- column:设置映射关系中的字段名,必须是sql语句中查询出的字段名
注意namespace命名空间的接口映射,接口中的方法名需要与select中的id名一致。其中cache时是开启二级缓存
XML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.serenity.mybatis.mapper.EmpMapper">
<cache/>
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</resultMap>
<select id="getAllEmp" resultMap="empResultMap">
select * from emp;
</select>
</mapper>
采用注解开发
java
//通过id查询用户,方法中存在多个参数时,所有参数前面必须加上@Param
@Select("select * from user where id=#{id}")
User getUserById(@Param("id") int id);
//增加用户
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
int addUser(User user);
//修改用户
@Update("update user set name=#{name},pwd=#{password} where id=#{id}")
int updateUser(User user);
//删除用户
@Delete("delete from user where id=#{uid}")
int deleteUser(@Param("uid") int id);
Mybatis工具包
java
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
String resource="mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
一对多和多对一的处理
java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp {
private int eid;
private String empName;
private Integer age;
private String sex;
private String email;
//多对一,创建这个一的对象
private Dept dept;
}
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
private Integer did;
private String deptName;
//一对多,创建这个对多的集合
List<Emp> emps;
}
以下是两张表的信息:
emp表

t_dept表

多对一映射处理
级联resulrMap
使用resultMap完成结果集映射,property中的dept是实体类Emp中设置的。
XML
<resultMap id="empAndDeptResultMapone" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<!--dept.did is on the POJO about property ,column is binding did of dept-->
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--selec emp information and some depy infoormotion-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapone">
select * from emp left join t_dept on emp.did=t_dept.did where emp.eid=#{eid}
</select>
进行多表查询测试:
java
@Test
public void testGetEmpAndDept(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDept(1);
System.out.println(emp);
}

association
其他地方与法一一样,只需要更改字段不一致部分。association专门处理多对一的映射关系。
property中的dept是对应emp中的属性名,
javaType中的Dept对应的是属性名的类型。
XML
<association property="dept" javaType="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
分布查询association+select
根据id查询员工信息


根据id查询部门信息


查询结果为:
java
@Test
public void testGetEmpAndDeptByStep(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAnddeptBystepOne(3);
System.out.println(emp);
}

一对多映射处理
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
private Integer did;
private String deptName;
//一对多,创建这个对多的集合
List<Emp> emps;
}
collection
ofType:表示集合存放的什么类型


测试:

分部查询collection+select


查询员工信息:


测试结果:

分布查询优点:延迟加载
想要实现延迟加载,必须在核心配置文件中设置全局配置信息。
lazyLoadingEnable:延迟加载的全局开关 ,开启时,所有关联对象都会延迟加载。设置为true
aggressiveLazyLoading :开启时,任何方法的调用都会加载该对象的所有属性,否则,每个属性会按需加载。设置为false
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql,此时可通过association和collection中的fetchType属性设置当前的分布查询是否所有延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"
XML
<!--Enable delayed loading-->
<setting name="lazyLoadingEnabled" value="true"/>
多条件查询
IF
if标签中的test为判断语句 是否为空来决定标签中的内容是否需要拼接到SQL语句 ,paramaterType可以指定SQL语句的参数类型,可以是基本数据类(int、string等),也可以是复杂数据类型(类和Map)
where
**where元素只会在至少有一个子元素的条件返回SQL子句的情况下才去插入"where"子句,而且,若语句的开头为"and"或"or",where元素也会将它们去除。**下面例子,如果第一个条件不成立,where自动去掉and。
但是where标签中没有内容时,此时where标签没有任何效果,不会自动生成where。
XML
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<if test="title!=null">
title=#{title}
</if>
<if test="author!=null">
and author=#{author}
</if>
</where>
</select>
set
wher无法将判断语句后面的and或or去掉,set元素会动态前置set关键字,同时也会删掉无关的逗号或and,or
XML
<update id="updateBlog" parameterType="map">
update blog
<set>
<if test="title!=null">
title=#{title},
</if>
<if test="author!=null">
author=#{author}
</if>
</set>
where id=#{id}
</update>
trim(定制标签)
trim作用位置与之前的where一致,添加前缀值where,删掉前缀文本and或or。
XML
<trim prefix="where" prefixOverrides="and|or">
...
</trim>
添加前缀值set,删掉后缀文本,
XML
<trim prefix="set" suffixOverrides=",">
...
</trim>
choose、when、otherwise
有时我们不想应用到所有的条件语句,只想要其中一项,choose能够满足我们的需求,它有点像Java中的switch语句。它能够按照提供了title就根据title查找,提供了author就按照author查找,若两者都没有提供,就返回所有符号条件的Blog。
- 当所有when中的条件都满足时,优先满足第一条。
- 当when的条件都不满足时,执行otherwise
- when至少有一个,otherwise最多只有一个
XML
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from blog
<where>
<choose>
<when test="title!=null">
title=#{title}
</when>
<when test="author!=null">
and author=#{author}
</when>
<otherwise>
and view=#{view}
</otherwise>
</choose>
</where>
</select>
foreach
map中存在一个集合,从集合中遍历id。
- collection:标识要遍历的数组或集合名
- item:标识数组中的每一个元素
- open:前缀
- close:后缀
- separator:每一个循环体的分隔符
XML
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="(" close=")" separator="or">
id=#{id}
</foreach>
</where>
</select>
SQL片段(不常用)
抽取SQL语句的公共部分
XML
<sql id="select_queryBlogIF_if">
<if test="title!=null">
title=#{title}
</if>
<if test="author!=null">
and author=#{author}
</if>
</sql>
需要使用的地方使用include标签引用即可
XML
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="select_queryBlogIF_if"></include>
</where>
</select>