1.ResultMap
resultMap
元素是 MyBatis 中最重要最强大的元素。ResultMap
的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。ResultMap
的优秀之处——你完全可以不用显式地配置它们。
@Data
public class User {
private int id;
private String name;
private String password;
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.password = pwd;
}
}
<!-- 结果集映射-->
<resultMap id="UserMap" type="User">
<!-- column数据库中的字段,property实体类中的属性-->
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" resultMap="UserMap">
select * from MyBatis.user where id =#{id}
</select>
2.日志
2.1 日志工厂
- SLF4J
- LOG4J :[重点]
- LOG4J2
- JDK_LOGGING
- COMMONS_LOGGING
- STDOUT_LOGGING:[重点]
- NO_LOGGING
6.STDOUT_LOGGING:标准日志输出
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
1.SLF4J
SLF4J:
- 可以控制每一条日志的输出格式
- 可以设置每一条日志的级别,更加细致地控制日志的生成过程
- 通过配置文件灵活的进行配置,不需要修改相应的代码
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j.properties
#将等级为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/xx.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
<settings>
<setting name="logImpl" value="SLF4J"/>
</settings>
日志对象,日志为当前类的class
Logger logger = Logger.getLogger(UserDaoTest.class);
日志级别
logger.info("info");
logger.debug("debug");
logger.error("error");
3.分页
目的:减少数据的处理量
//分页查询用户
List<User> getUserByLimit(Map<String,Integer> map);
<select id="getUserByLimit" parameterType="map" resultType="user">
select * from MyBatis.user limit #{startIndex},#{pageSize}
</select>
@Test
public void testGetUserByLimit(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Integer> map = new HashMap<String,Integer>();
map.put("startIndex",0);
map.put("pageSize",2);
List<User> userList=mapper.getUserByLimit(map);
userList.forEach(System.out::println);
sqlSession.close();
}
4.MyBatis执行流程
5.多对一
5.1按照查询嵌套处理(子查询)
StudentMapper里写方法:
public interface StudentMapper {
//查询所有的学生信息,以及对应的老师信息
public List<Student> getStudent();
}
<select id="getStudent" resultMap="StudentTeacher" >
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"></result>
<result property="name" column="name"></result>
<!--复杂的属性需要单独处理
对象:association
集合:collection
-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"></association>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{tid}
</select>
实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
//学生需要关联一个老师
private Teacher teacher;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
}
配置文件中给实体类起别名:
<!-- 可以给实体类起别名-->
<typeAliases>
<typeAlias type="com.xx.pojo.Teacher" alias="Teacher"/>
<typeAlias type="com.xx.pojo.Student" alias="Student"/>
</typeAliases>
5.2根据结果嵌套查询(联表查询)
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.`name` sname,t.id tid,t.`name` tname
FROM student s,teacher t
WHERE s.tid=t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"></result>
</association>
</resultMap>
6.一对多
实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
//学生需要关联一个老师
private int tid;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
// 一个老师拥有多个学生
private List<Student> students;
}
<select id="getTeacher" resultMap="TeacherStudents">
select s.id sid,s.`name` sname,t.`name` tname,t.id tid
from student s ,teacher t
where s.tid =#{tid}
</select>
<resultMap id="TeacherStudents" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--javaType:指定属性的类型
ofType:集合中的泛型信息
-->
<collection property="students" ofType="student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
7.动态sql
动态sql就是指根据不同的条件生成不同的sql语句
动态sql是在sql的基础上可以执行逻辑
7.1 IF
开启驼峰命名:
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
生成UUID:
public class IDUtils {
public static String getId(){
return UUID.randomUUID().toString().replace("-","");
}
}
核心代码:
//查询博客
List<Blog> queryBlogIf(Map map);
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog where 1=1
<if test="title!=null">
and title=#{title}
</if>
<if test="author!=null" >
and author =#{author}
</if>
</select>
测试代码:
@Test
public void queryBlogIf(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap<>();
map.put("title","Java如此简单");
List<Blog> blogs = mapper.queryBlogIf(map);
blogs.forEach(System.out::println);
}
}
7.2 where
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title!=null">
and title=#{title}
</if>
<if test="author!=null" >
and author =#{author}
</if>
</where>
7.3 choose
List<Blog> queryBlogChoose(Map map);
<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 views = #{views}
</otherwise>
</choose>
</where>
</select>
@Test
public void queryBlogChoose(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap<>();
map.put("author","狂神说");
List<Blog> blogs = mapper.queryBlogChoose(map);
blogs.forEach(System.out::println);
}
7.4 trim(,where,set)
//更新博客
int updateBlog(Map map);
<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>
@Test
public void updateBlog(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("title","自然语言处理");
map.put("author","小张");
map.put("id","7a07c70f6d034e528a409f5294556d76");
int i = mapper.updateBlog(map);
System.out.println(i);
sqlSession.commit();
sqlSession.close();
}
7.5 sql片段
作用:抽取公共部分,最好基于单表进行操作,不要存在where
标签
<sql id="if-title-author">
<if test="title!=null">
and title=#{title}
</if>
<if test="author!=null" >
and author =#{author}
</if>
</sql>
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
7.6 foreach
//forEach查询
List<Blog> queryBlogForeach(Map map);
<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>
@Test
public void queryBlogForEach(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
map.put("ids",ids);
List<Blog> blogs = mapper.queryBlogForeach(map);
blogs.forEach(System.out::println);
sqlSession.close();
}
8. 缓存
存在内存中的临时数据
- 只要开启了二级缓存,在同一个mapper下就有效
- 所有数据都会放到一级缓存中
- 只有当会话提交,或者关闭的时候,也就是一级缓存死的时候,才会提交到二级
开启二级缓存:
全局配置:
<setting name="cacheEnabled" value="true"/>
再在相关的mapper.xml中添加以下代码
<cache/>