Maven仓库
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
优点:
环境搭建
数据库
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user` (`id`,`name`,`pwd`) VALUES
(1,'狂神','123456'),
(2,'张三','123456'),
(3,'李四','123456')
新建Maven项目:Mybatis-Study,删除src作为父工程,导入依赖
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.46version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.18version>
dependency>
dependencies>
第一个Mybatis程序
创建一个module,mybatis-01:
编写mybatis配置文件:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="pOOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
dataSource>
environment>
environments>
configuration>
编写mybatis工具类,获取sqlsessionFactory和sqlSession
//sqlSessionFactory -----> sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
// 第一步:获取sqlSessionFactory对象!
String resource = "mybbatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// 创建sqlSession,SqLSession完全包含了面向数据库执行SQL命令所需的所有方法。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
编写代码:
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
Dao及其实现类,接口实现类由原来JDBC的impl转换为一个Mapper配置文件!
public interface UserDao {
List<User> getUserList();
}
<mapper namespace="com.kuang.dao.UserDao">
<select id="selectBlog" resultType="com.kuang.pojo.User">
select * from mybatis.user
select>
mapper>
Junit测试:
public class UserDaoTest {
@Test
public void test(){
// 1.获取SqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 方式一:getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
//方式二:
List<User> userList = sqlSession.selectList("com.kuang.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
// 3.关闭sqlSession
sqlSession.close();
}
}
报错:没有配置mapper文件
<configuration>
<mappers>
<mapper resource="com/kuang/dao/UserMapper.xml"/>
mappers>
configuration>
还是报错:可能存在错误,是因为配置文件没有生效,我们在子pom和父pom中都加入如下:
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
解决方案:把mybatis-config.xml文件上文件头的encoding="UTF-8"改为encoding="UTF8"
解决方案:数据库连接的时候加上时区:
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/>
成功:
查询语句
增加语句
标签为
//插入用户int addUser(User user);
在Mapper.xml中,如果没有传参,他还是可以拿到实体类的属性,直接通过#{}即可。
<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into mybatis.user(id,name,pwd) values (#{id},#{name},#{pwd})
insert>
增删改一定要提交事务!!!!!!!!!
public void test2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.addUser(new User(4,"ran","123456"));
//提交事务
sqlSession.commit();
sqlSession.close();
}
修改语句
标签为
//修改用户
int updateUser(User user);
<update id="updateUser" parameterType="com.kuang.pojo.User">
update mybatis.user set name = #{name},pwd = #{pwd} where id = #{id}
update>
@Test
public void test3(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.updateUser(new User(4,"ranhaifeng","123456"));
//提交事务
sqlSession.commit();
sqlSession.close();
}
删除语句
标签为
//删除用户
int deleteUser(int id);
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id}
delete>
@Test
public void test4(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.deleteUser(4);
//提交事务
sqlSession.commit();
sqlSession.close();
}
背景
在插入和修改的时候,如果传入一个User,而User的字段全限定名非常长,那么就会十分冗余。
实现
Map具有以下优点:
Map实现插入:
int insertUser(Map<String,Object> map);
<insert id="insertUser" parameterType="map">
insert into mybatis.user(id,name,pwd) values (#{helloid},#{helloname},#{hellopassword})
insert>
public class UserDaoTest {
@Test
public void test(){
// 1.获取SqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("helloid",4);
map.put("helloname","ranhaifeng");
map.put("hellopassword","123456");
userDao.insertUser(map);
System.out.println(map);
sqlSession.commit();
sqlSession.close();
}
}
public interface UserDao {
List<User> selectUser(String val);}
方式1:直接在传入参数时带上通配符
List<User> users = userDao.selectUser("%张%");
<select id="selectUser" parameterType="String" resultType="com.kuang.pojo.User">
select * from mybatis.user where name like #{val}
select>
会有sql注入的危险!
方式2:直接在sql语句中写死(推荐)
List<User> users = userDao.selectUser("张");
<select id="selectUser" parameterType="String" resultType="com.kuang.pojo.User">
select * from mybatis.user where name like "%"#{val}"%"
select>
核心配置文件
我们可以通过properties属性来实现引用配置文件,上述的property中的value值都是可以动态替换的,即可以在典型的Java属性文件中配置,也可通过Properties元素的子元素来传递。
编写一个配置文件db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username=admin
password=root
在Mybatis核心配置文件中引入:
可以直接引入外部文件
可以在其中增加一些properties
driver=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername=rootpassword=admin
<configuration>
<properties resource="db.properties"/>
configuration>
当外部配置文件和核心配置文件内的properties冲突时,优先外部配置文件
问题引入
实现
普通起别名方法
<!-- 给实体类起别名 -->
<typeAliases>
<typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>
<mapper namespace="com.kuang.dao.UserDao">
<select id="selectUser" parameterType="String" resultType="User">
select * from mybatis.user where name like "%"#{val}"%"
select>
mapper>
也可以指定一个包名,Mybatis会在扫描这个包的Java Bean,在没有注解的情况下,默认别名就是这个类首字母小写的类名(其实大写也跑的出来!)
<!-- 给实体类起别名 -->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
直接在实体类上通过注解**@Alias**也可以指定别名(一定要做第二步,不然会失效!)
@Alias("hello")
public class User {
private int id;
private String name;
private String pwd;
}
介绍
这是Mybatis中及其重要的调整设置!
方式一:
<mappers>
<mapper resource="com/kuang/dao/UserMapper.xml"/>
mappers>
方式二:使用class文件绑定注册:
<mappers>
<mapper class="com.kuang.dao.UserDao"/>
mappers>
注意点:
方式三:使用扫描包进行绑定:(接口和它的Mapper配置文件必须同名且在同一个包下)
<mappers>
<package name="com.kuang.dao"/>
mappers>
SqlSessionFactoryBuilder
一旦创建就不需要了,局部变量
SqlSessionFactory
SqlSession
属性名和字段名不一致问题
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}
<mapper namespace="com.kuang.dao.UserDao">
<select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User">
select * from mybatis.user where id = #{id}
select>
mapper>
测试出现问题:
解决方式1:起别名!
select id,name,pwd as password from mybatis.user where id = #{id}
解决方式2:resultMap结果集映射
结果集映射:
id name pwdid name pwssword
介绍
如果一个数据库操作出现了问题,我们需要拍错,日志就是最好的助手。在Mybatis中具体使用哪一个日志实现,在setting中指定!
标准日志工厂实现
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
configuration>
介绍
使用
先导入包
<dependencies>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
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/kuang.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
配置log4j为日志的实现:
<configuration>
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
configuration>
使用!直接测试运行刚才的查询
简单使用:
在要使用log4j的类中,导入包import org.apache.log4j.Logger
日志对象,参数为当前类的class对象
static Logger logger = Logger.getLogger(UserDaoTestTwo.class);
打不开.log文件?
测试
public class UserDaoTestTwo {
static Logger logger = Logger.getLogger(UserDaoTestTwo.class);
@Test
public void getUserList(){
logger.info("info:进入了testLog4j");
logger.debug("info:进入了testLog4j");
logger.error("info:进入了testLog4j");
}
}
为什么分页?
减少数据的处理量
Limit分页
select * from user limit 0,2; //从下标第0个开始,每页显示2个人
select * from user limit 3; //从下标第0个开始,每页显示3个人,相当于[0,3]
Mybatis分页
思路:分页需要传2个limit参数过去,多个参数优先考虑map,通过往map中放入2个键值对,然后在SQL语句中取map的key,从而拿到2个参数。
接口
List<User> getUserByLimit(Map<String,Object> map);
Mapper.xml
<select id="getUserByRowBounds" resultType="user">
select * from mybatis.user
select>
测试
@Test
public void getUserList(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
//RowBounds实现
RowBounds rowBounds = new RowBounds(1, 2);
List<User> userList = sqlSession.selectList("com.kuang.dao.UserDao.getUserByRowBounds", null, rowBounds);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
接口
List<User> getUserByRowBounds(Map<String,Object> map);
mapper
<select id="getUserByRowBounds" resultType="user">
select * from mybatis.user
select>
测试
@Test
public void getUserList(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
//RowBounds实现
RowBounds rowBounds = new RowBounds(1, 2);
List<User> userList = sqlSession.selectList("com.kuang.dao.UserDao.getUserByRowBounds", null, rowBounds);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
实现
<mappers>
<mapper class="com.kuang.dao.UserDao"/>
mappers>
@Select("select * from mybatis.user limit #{startIndex},#{pageSize}")
List<User> getUserByLimit(@Param("startIndex") int startIndex,@Param("pageSize") int pageSize);
@Test
public void getUserList(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userByLimit = userDao.getUserByLimit(0,2);
System.out.println(userByLimit);
sqlSession.close();
}
@Param
#{}和${}
实现自动提交
//sqlSessionFactory -----> sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
// 第一步:获取sqlSessionFactory对象!
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// 创建sqlSession,SqLSession完全包含了面向数据库执行SQL命令所需的所有方法。
// 设置为true,实现自动提交
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
}
问题
使用注解开发无法解决字段名和实体类名不一致的问题!
介绍
环境搭建
数据库
CREATE TABLE `teacher` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师'); CREATE TABLE `student` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, `tid` INT(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, 小明, 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, '小红', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, '小张', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, '小李', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, '小王', 1);
实体类:
学生
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {
private int id;
private String name;
//学生关联一个老师
private Teacher teacher;
}
老师
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Teacher {
private int id;
private String name;
}
dao接口:StudentMapper、TeacherMapper
mapper文件:StudentMapper.xml、TeacherMapper.xml
需求
查出所有学生的信息和对应老师的信息
问题
<mapper namespace="com.kuang.dao.StudentMapper">
<select id="getStudent" resultType="student">
select s.id,s.name,t.name from student s,teacher t where s.tid = t.id
select>
mapper>
SQL语句在控制台验证正确,但是结果却错误!
思路
teacher是null,变相相当于是字段名和数据库名不一致问题,返回类型应该是resultmap
按照结果嵌套处理
<mapper namespace="com.kuang.dao.StudentMapper">
<select id="getStudent" resultMap="StudentTeacher">
select s.id sid,s.name sname,t.id ttid,t.name tname from student s,teacher t where s.tid = t.id
select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" column="tid" javaType="Teacher">
<result property="id" column="ttid"/>
<result property="name" column="tname"/>
association>
resultMap>
mapper>
按照过程嵌套处理
<mapper namespace="com.kuang.dao.StudentMapper">
<select id="getStudent" resultMap="StudentTeacher">
select * from student
select>
<resultMap id="StudentTeacher" type="student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{tid}
select>
mapper>
比如:一个老师拥有多个学生!
对于老师而言,就是一对多的关系!
环境搭建
学生
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {
private int id;
private String name;
private int tid;
}
老师
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Teacher {
private int id;
private String name;
//一个老师拥有多个学生
private List<Student> students;
}
接口
public interface TeacherMapper {
//获取指定老师下的所有学生及老师的信息
Teacher getTeacher(@Param("tid") int id);
}
按结果嵌套查询
<mapper namespace="com.kuang.dao.TeacherMapper">
<select id="getTeacher" resultMap="TeacherStudent">
select s.name sname,s.id sid,t.name tname,t.id tid
from student s,teacher t
where s.tid = t.id and t.id = #{tid}
select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
collection>
resultMap>
mapper>
子查询方式(按照过程嵌套处理)
<mapper namespace="com.kuang.dao.TeacherMapper">
<select id="getTeacher" resultMap="TeacherStudent">
select * from mybatis.teacher where id = #{tid}
select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="name"/>
<collection property="students" ofType="Student" javaType="ArrayList" select="getStudent" column="id"/>
resultMap>
<select id="getStudent" resultType="Student">
select * from mybatis.student where tid = #{tid}
select>
mapper>
注意
介绍
动态SQL就是根据不同条件生成不同的SQL语句
环境搭建
开启驼峰命名:
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
configuration>
实体类
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;
private int views;
}
接口
public interface BlogMapper {
// 插入数据
int addBlog(Blog blog);
}
Mapper.xml
<mapper namespace="com.kuang.dao.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into mybatis.blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views})
insert>
mapper>
测试
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IdUtils.getId());
blog.setTitle("Mybatis");
blog.setAuthor("Q");
blog.setCreateTime(new Date());
blog.setViews(9999);
blogMapper.addBlog(blog);
blog.setId(IdUtils.getId());
blog.setTitle("Spring");
blogMapper.addBlog(blog);
blog.setId(IdUtils.getId());
blog.setTitle("Java");
blogMapper.addBlog(blog);
blog.setId(IdUtils.getId());
blog.setTitle("微服务");
blogMapper.addBlog(blog);
sqlSession.close();
}
}
实现
不确定前端到底是通过什么样的值进行查询。title?author?
public interface BlogMapper {
// 查询数据
List<Blog> getBlogByIf(Map map);
}
mapper
<mapper namespace="com.kuang.dao.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into mybatis.blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views})
insert>
<select id="getBlogByIf" parameterType="string" resultType="Blog">
select * from mybatis.blog where 1=1
<if test="biaoti != null">
and title = #{biaoti}
if>
select>
mapper>
select * from mybatis.blog where 1=1
是表示如果没有任何参数传进来,我们就查询所有的数据。
表示如果有客户想通过标题查询,即biaoti这个参数(Map的键,客户搜索的值)传进来,那么在前面的SQL语句后拼接判断条件,即select * from mybatis.blog where 1=1 and title = #{biaoti}
。测试查询
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
HashMap<String, Object> map = new HashMap();
map.put("biaoti","java"); // 访问查询接口穿过去的参数是biaoti,值是java
List<Blog> blogs = blogMapper.getBlogByIf(map);
System.out.println(blogs);
sqlSession.close();
}
}
where
看一下下面的mapper中的SQL语句:
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
HashMap<String, Object> map = new HashMap();
// map.put("biaoti","java");
map.put("guankan",3333);
List<Blog> blogs = blogMapper.getBlogByIf(map);
System.out.println(blogs);
sqlSession.close();
}
}
在上面的语句中,如果我只传入guankan
参数作为查询条件,而不传入biaoti
,会出现什么问题呢?
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
HashMap<String, Object> map = new HashMap();
// map.put("biaoti","java");
map.put("guankan",3333);
List<Blog> blogs = blogMapper.getBlogByIf(map);
System.out.println(blogs);
sqlSession.close();
}
}
针对上面这种情况,mybatis推出了
,他可以智能判断是否传入第一个查询参数,如果传入,会自动为后面的参数加入and
,如果不传入,会去除第二个参数的and
<mapper namespace="com.kuang.dao.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into mybatis.blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views})
insert>
<select id="getBlogByIf" parameterType="string" resultType="Blog">
select * from mybatis.blog
<where>
<if test="biaoti != null">
title = #{biaoti}
if>
<if test="guankan!=null">
views = #{guankan}
if>
where>
select>
mapper>
choose
有时候我们不想应用到所有的条件语句,只想选择其中一项,那么用choose
相当于switch,when
相当于case
<mapper namespace="com.kuang.dao.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into mybatis.blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views})
insert>
<select id="getBlogByIf" parameterType="string" resultType="Blog">
select * from mybatis.blog
<where>
<choose>
<when test="biaoti!=null">
title = #{biaoti}
when>
<when test="guankan!=null">
views = #{guankan}
when>
<otherwise>
author = #{zuozhe}
otherwise>
choose>
where>
select>
mapper>
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
HashMap<String, Object> map = new HashMap();
map.put("biaoti","java");
map.put("guankan",5555);
map.put("zuozhe","QQQ");
List<Blog> blogs = blogMapper.getBlogByIf(map);
System.out.println(blogs);
sqlSession.close();
}
}
即使我们传入个三个参数,但它只会选择一个,默认是自上而下,因此结果是根据title查询的:
set
在更改某个数据的时候,我们通常使用 update xxx set a = #{a},b=#{b},如果第一个参数不传,逗号无法处理,在这个基础上,set可以完美解决。
<mapper namespace="com.kuang.dao.BlogMapper">
<insert id="addBlog" parameterType="blog">
insert into mybatis.blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views})
insert>
<select id="getBlogByIf" parameterType="string" resultType="Blog">
select>
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="biaoti !=null">
title = #{biaoti},
if>
<if test="guankan !=null">
views = #{guankan}
if>
set>
where id = #{idd}
update>
mapper>
所谓的动态sql,本质还是sql语句,只是我们可以在SQL层面,增加逻辑代码!
SQL片段
有的时候,我们有很多复用的SQL片段,这个时候我们可以进行SQL的抽离和引用:
使用SQL标签
抽取公共部分
<sql id="if-biaoti-guankan">
<if test="biaoti !=null">
title = #{biaoti},
if>
<if test="guankan !=null">
views = #{guankan}
if>
标签引用
<mapper namespace="com.kuang.dao.BlogMapper">
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<include refid="if-biaoti-guankan"/>
set>
where id = #{idd}
update>
mapper>
最好基于单边查询,且不要存在where标签
Foreach
mapper
<mapper namespace="com.kuang.dao.BlogMapper">
<select id="getBlogByForeach" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="item" open="and (" close=")" separator="or">
id = #{item}
foreach>
where>
select>
mapper>
测试:
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
HashMap<String, Object> map = new HashMap();
List<Integer> list = new ArrayList();
list.add(1);
list.add(2);
map.put("ids",list);
List<Blog> blogs = blogMapper.getBlogByForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
}
动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
建议先把sql完整写出来然后再用动态SQL拼接。
简介
简介
一级缓存也叫本地缓存:
测试
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = blogMapper.getBlogByTitle("Java");
Blog blog2 = blogMapper.getBlogByTitle("Java");
System.out.println(blog2);
sqlSession.close();
}
}
缓存失效的原因
查询不同的东西
增删改操作,可能会改变原来的数据,所以必定会刷新缓存!(先查询1,再修改2,再次查询1,会进行三次SQL语句操作,而不是2次,缓存是针对整体数据库而言,而不是单个数据)
查询不同的Mapper.xml
手动清理缓存!
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = blogMapper.getBlogByTitle("Java");
sqlSession.clearCache(); //手动清理缓存
Blog blog2 = blogMapper.getBlogByTitle("Java");
System.out.println(blog2);
sqlSession.close();
}
}
二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存。
基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
工作机制:
开启步骤:
开启全局缓存(默认是开启的,为了代码规范和可读性,我们需要显式开启让别人看到):
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
settings>
configuration>
在要使用二级缓存的mapper中开启:
<mapper namespace="com.kuang.dao.BlogMapper">
<cache/>
<select id="getBlogByTitle" resultType="Blog" parameterType="string">
select * from mybatis.blog where title = #{biaoti}
select>
mapper>
也可以自定义缓存参数:
<mapper namespace="com.kuang.dao.BlogMapper">
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
<select id="getBlogByTitle" resultType="Blog" parameterType="string">
select * from mybatis.blog where title = #{biaoti}
select>
mapper>
测试:
<!--命名空间绑定一个对应的Dao接口-->
<mapper namespace="com.kuang.dao.BlogMapper">
<!-- 在当前mapper.xml中使用二级缓存 -->
<cache/>
<select id="getBlogByTitle" resultType="Blog" parameterType="string">
select * from mybatis.blog where title = #{
biaoti}
</select>
</mapper>
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession2 = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
BlogMapper blogMapper2 = sqlSession2.getMapper(BlogMapper.class);
Blog blog = blogMapper.getBlogByTitle("Java");
sqlSession.close();
Blog blog2 = blogMapper2.getBlogByTitle("Java");
System.out.println(blog2);
sqlSession2.close();
}
}
public class Blog implements Serializable {
private String id;
private String title;
private String author;
private Date createTime;
private int views;
}
小结
介绍
Ehcache是一种广泛使用的开源ava分布式缓存。主要面向通用缓存。
使用
导包
<dependencies>
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.1.0version>
dependency>
dependencies>
project>
ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="./tmpdir/Tmp_EhCache"/>
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
ehcache>
测试,成功
public class UserDaoTestTwo {
@Test
public void TeacherTest(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession2 = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
BlogMapper blogMapper2 = sqlSession2.getMapper(BlogMapper.class);
Blog blog = blogMapper.getBlogByTitle("Java");
sqlSession.close();
Blog blog2 = blogMapper2.getBlogByTitle("Java");
System.out.println(blog2);
sqlSession2.close();
}
}