MyBatis学习总结大全:
- MyBatis学习总结第一天
- MyBatis学习总结第二天
- MyBatis学习总结第三天
今日大纲
- 动态sql
- 缓存
- 接口绑定
- 或者叫动态代理
ResultType
1、动态sql
相当于条件查询,在代码中使用if语句来拼装sql语句,它会造成资源浪费,而且,不易于维护。If、switch语句是Java代码之罪。
在写sql语句的时候,直接进行拼装。
特殊字符转义
< < 小于
> > 大于
& & 和号
' ' 省略号
" " 引号
< if>标签:
标签,相当于代码中的if(){}else{}
它帮我们做数据判断
<select id="getUsers" resultType="user">
select * from t_user
where 1=1
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="pwd !=null and pwd !='' ">
and pwd =#{pwd}
</if>
<if test="age > 23">
and name ='王思聪'
</if>
</select>
< where>标签
标签就想到与sql语句中where条件,当where标签内的if判断条件执行,才执行where标签,如果if不执行,where也不执行,所以 1=1 就省略掉了。
Where标签,会自动判断sql语句,如果第一个and开始的,就省略掉,一般情况下,在if判断条件中都加and关键字。
<select id="getUsers" resultType="user">
select * from t_user
<where>
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="pwd !=null and pwd !='' ">
and pwd =#{pwd}
</if>
<if test="age > 23">
and name ='王思聪'
</if>
</where>
</select>
< choose>标签
标签就相当于代码中switch,标签:当条件满足的时候执行when标签内容,当所有的when标签内容不满足时,执行默认标签中的内容。
<select id="getUsers1" resultType="user">
select * from t_user
<where>
<choose>
<when test="name != null and name !=''">
and name= #{name}
</when>
<otherwise>
and age > 23
</otherwise>
</choose>
</where>
</select>
< sql >和< include >
标签:用于定义sql语句
标签:用于引用标签定义的sql语句,这个引用可以在sql语句的任何位置
<sql id="select">
id,name,pwd
</sql>
<sql id="from">
from t_user
</sql>
<select id="getUsers2" resultType="user">
<!-- select * from t_user t where t.id in(select id from t_user1 where name =?)
sql:语句的拆分,一般不用于单表操作,一般用于多表操作
include:引用sql语句,可以在任何位置
-->
select
<include refid="select"/>
<include refid="from"/>
</select>
< bind>标签
标签用于给参数追加数据,随便添加
<select id="getUserByName" resultType="user">
<!-- bind:给参数追加内容,写的方式 '%'+name+'%'
现在讲参数进行追加,然后再进行数据判断
如果参数为空:会报错
-->
<bind name="name" value="name+'123'"/>
select * from t_user
<where>
<if test="name != null and name!='' ">
name like #{name}
</if>
</where>
</select>
< set>标签
标签主要用于update语句。相对于update语句中set关键字,它会自动消除多余的”,”
<!-- set 标签应用-->
<update id="updateUser">
<!-- update t_user set name=? and pwd=? where id =? -->
update t_user
<set>
<if test="name != null and name !=''">
name = #{name},
</if>
<if test="pwd != null and pwd !='' ">
pwd = #{pwd}
</if>
</set>
<where>
id=#{id}
</where>
</update>
< foreach>标签
< foreach>标签,主要用循环遍历,
Select * from t_user where id in(name),name就可以使用foreach
<!-- foreach应用 -->
<select id="findUsers" resultType="user">
select * from t_user
<where>
id in
<!--
collection:集合对象
open:指的是以什么开始
close:指的是以什么结尾,与open成对出现
separator:指的数据以什么进行分割
item:指的遍历的数据项
mybatis的会自动给string数据添加'',不需要我们手动添加
-->
<foreach collection="list" open="(" separator="," close=")" item="ids">
#{ids}
</foreach>
</where>
</select>
<select id="findUsersByName" resultType="user">
select * from t_user
<where>
name in
<foreach collection="list" open="(" separator="," close=")" item="names">
#{names}
</foreach>
</where>
</select>
< trim>标签
< trim>标签在mybatis里面是去除and|or|,
<select id="queryUsers" resultType="user">
select * from t_user
<!--
prefix:前缀
suffix:后缀
prefixOverrides:前缀结束,去掉and|or关键字
suffixOverrides:后缀结束,去掉and|or关键字
<where><set>本身自带了去掉and|or|,的功能
-->
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="pwd !=null and pwd !='' ">
and pwd =#{pwd}
</if>
<if test="age > 23">
and name ='王思聪'
</if>
</trim>
</select>
简单类型传递参数
<!-- 简单类型参数传递:现在一次传递多个参数
如果是多个简单类型的参数使用[param参数下标从1开始]
在占位符中的name值是:[param参数下标从1开始],不是参数名称
-->
<select id="findUsersByParam" resultType="user">
select * from t_user
<where>
<if test="param1 != null and param1 !='' ">
and name = #{param1}
</if>
<if test="param2 !=null and param2 !='' ">
and pwd =#{param2}
</if>
<if test="param3 > 23">
and name ='王思聪'
</if>
</where>
</select>
<!-- 简单类型参数传递:一次传递一个参数
作为判断条件的时候:使用_parameter来进行判断
占位符中应用还是参数名称
-->
<select id="findUsersByParam1" resultType="user">
select * from t_user
<where>
<if test="_parameter != null and _parameter != ''">
name = #{name}
</if>
</where>
</select>
接口类:
public interface UserMapper {
List<User> getUsers(Map<String, Object> map);
List<User> getUsers1(User user);
List<User> getUsers2();
List<User> getUserByName(User user);
int updateUser(User user);
List<User> findUsers(List<Integer> ids);
List<User> findUsersByName(List<String> names);
List<User> queryUsers(User user);
List<User> findUsersByParam(String name,String pwd, Integer age);
List<User> findUsersByParam1(String name);
}
测试类:
package com.bjsxt.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.bjsxt.mapper.UserMapper;
import com.bjsxt.pojo.User;
import com.bjsxt.utils.MybatisUtil;
public class TestMybatis {
private SqlSession session ;
@Before
public void getSession(){
session = MybatisUtil.getSession();
}
@After
public void closeSession(){
MybatisUtil.closeSession();
}
/**
*
* @Description: foreach应用
* @author mao
* @date 2017年10月11日
*/
@Test
public void findUsers(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<Integer> ids = new ArrayList<>();
ids.add(2);
ids.add(3);
ids.add(6);
ids.add(7);
List<User> findUsers = mapper.findUsers(ids);
for (User user : findUsers) {
System.out.println(user);
}
}
@Test
public void findUsersByName(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<String> names = new ArrayList<>();
names.add("王二麻子");
names.add("张三丰");
List<User> findUsersByName = mapper.findUsersByName(names);
for (User user : findUsersByName) {
System.out.println(user);
}
}
@Test
public void queryUsers(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("王二麻子");
List<User> queryUsers = mapper.queryUsers(user);
for (User user2 : queryUsers) {
System.out.println(user2);
}
}
/**
*
* @Description: 简单类型参数传递:多个简单类型
* @author mao
* @date 2017年10月11日
*/
@Test
public void findUsersByParam(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> findUsersByParam = mapper.findUsersByParam("王二麻子", "12345", 22);
for (User user : findUsersByParam) {
System.out.println(user);
}
}
@Test
public void findUsersByParam1(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> findUsersByParam1 = mapper.findUsersByParam1("王二麻子");
for (User user : findUsersByParam1) {
System.out.println(user);
}
}
@Test
public void getUsers(){
/**
* 模糊查询
* 字符拼接查询
* 使用代码进行模糊查询,它效率很低
* if(){}else{}称之为代码之罪
* mybatis提供了动态sql,可以在sql中直接使用一些判断条件
*/
StringBuffer sb = new StringBuffer();
sb.append("select * from t_user where 1=1 ");
User user = new User();
if(user.getName() !=null){
sb.append(" and name= XXX");
}
if(user.getPwd() != null){
sb.append(" and pwd=XXX");
}
//执行sql
}
@Test
public void getUserDymic(){
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("name", "王二麻子");
// map.put("pwd", "12345");
// map.put("age", 26);
List<User> users = mapper.getUsers(map);
for (User user : users) {
System.out.println(user);
}
}
@Test
public void getUsers1(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
//user.setName("王二麻子");
List<User> users1 = mapper.getUsers1(user);
for (User user2 : users1) {
System.out.println(user2);
}
}
@Test
public void getUsers3(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users2 = mapper.getUsers2();
for (User user : users2) {
System.out.println(user);
}
}
@Test
public void getUserByName(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("张");
List<User> userByName = mapper.getUserByName(user);
for (User user2 : userByName) {
System.out.println(user2);
}
}
@Test
public void updateUser(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("张666");
//user.setPwd("456");
user.setId(3);
int updateUser = mapper.updateUser(user);
session.commit();
System.out.println(updateUser);
}
}
Sql拼接:
1.Java代码
2.Mybatis提供的动态sql
3.不使用Java代码和mybatis提供的动态sql:主要用报表
报表:经过封装后,还是jsp或者html,直接操作数据库,在报表工具中直接写的是sql语句。
<!-- 不使用Java代码 和 mybatis的标签拼接sql查询数据库数据 -->
<select id="getUsersByParams" resultType="user">
select * from t_user
where
(#{name} is null or name= #{name})
and (#{pwd} is null or pwd = #{pwd})
</select>
测试:
public void getUsers6(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("王二麻子");
List<User> usersByParams = mapper.getUsersByParams(user);
for (User user2 : usersByParams) {
System.out.println(user2);
}
}
缓存:
就是将数据放到内存中,电商项目,它的很多数据都是放在缓存中的。提高查询效率。但是mybatis的缓存做的不好,有大量数据冗余。
一级缓存
一级缓存:SqlSession,默认开启的,直接使用。
查询一条数据,又查询同样的一条数据,执行sql语句,查询第一条数据的时候,已经将数据放到一级缓存里面,在Sqlsession 没有关闭的情况下,查询同样的一条数据是从是缓存获取,不执行sql语句。
是依据 映射文件中标签中id属性值进行缓存(statementid进行缓存的)
@Test
public void getUserById(){
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("id", 3);
User userById = mapper.getUserById(map);
System.out.println(userById);
Map<String, Object> map1 = new HashMap<>();
map1.put("id", 3);
User userById1 = mapper.getUserById2(map1);
System.out.println(userById1);
}
配置文件:
<select id="getUserById" resultType="user">
select * from t_user where id = #{id}
</select>
<select id="getUserById2" resultType="user">
select * from t_user where id = #{id}
</select>
二级缓存
二级缓存:SqlSessionFactory,开启需要在映射文件中进行配置
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:
映射语句文件中的所有 select 语句将会被缓存。
映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
<?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">
<!--
namespace:相当于包的概念
要保证在一个映射文件中,保证statementid为唯一
-->
<mapper namespace="com.bjsxt.mapper.UserMapper">
<!--
<if>标签:相当于java代码中的if语句
if:简单类型传递
if标签:Java代码中的if判断条件 使用的是 && ||
在if标签中使用的是 and
-->
<select id="getUsers" resultType="user">
select * from t_user
where 1=1
<if test="_parameter != null and _parameter !='' ">
and name like #{name}
</if>
</select>
<!-- if语句的:对象和集合类型传递 -->
<select id="getUsers1" resultType="user">
select * from t_user
where 1=1
<if test="name != null and name !='' ">
and name like #{name}
</if>
</select>
<!-- if语句:多个判断条件,
where标签:去掉sql语句的where关键字
mybatis会自动的进行判断,再进行删除
它会自动判断,它内部的语句第一个 关键字是否是and 如果是,自动的去掉
所以,一般使用where标签,它内部的所有if判断条件都添加and关键字
-->
<select id="getUsers2" resultType="user">
select * from t_user
<where>
<if test="name != null and name !='' ">
and name like #{name}
</if>
<if test="age > 33">
and age > 33
</if>
</where>
</select>
<!--
choose标签:就相当于Java代码中的switch语句,当一个条件成立的话,后面的所有判断条件都不执行
switch(falg){
case falg:xxx; ==> when
case falg:xxx; ==> when
default: ==》otherwise
XXX;
}
-->
<select id="getUsers3" resultType="user">
select * from t_user
<where>
<choose>
<when test="name != null and name != ''">
and name like #{name}
</when>
<when test="age > 33">
and age > 33
</when>
<otherwise>
and pwd ='zhangsanf'
</otherwise>
</choose>
</where>
</select>
<!--
bind标签:相当于字符串拼接,它可以在参数的前后添加内容
name属性值:参数名称
value属性值:对参数进行改造
-->
<select id="getUsers4" resultType="user">
<bind name="name" value="'%'+name+'%'"/>
<!--
先进行数据添加,再进行数据判断,
参数为空,会报错,bind报错
-->
select * from t_user
<where>
<if test="name != null and name != ''">
and name like #{name}
</if>
</where>
</select>
<!--
set标签:它就相当于 update语句set关键字,set关键字对自动去掉,号
-->
<update id="updateUser">
<!-- update t_user set name=#{name} , age =#{age} where id=#{id} -->
update t_user
<set>
<if test="name != null and name != ''">
name=#{name},
</if>
<if test="age != null">
age=#{age},
</if>
</set>
<where>
<if test="id != null">
id=#{id}
</if>
</where>
</update>
<!-- foreach标签:相当于Java代码中的for循环
需求:查询该集合中主键的值
collection:指的是集合对象,对应的传递过来的参数集合类型
open:以什么开始
separator:数据以什么分割
close:以什么结尾,与open成单出现
item:参数名称,对应传递过来的参数名称
如果遍历的是string类型,mybatis会自动的添加''号,不需要我们手动添加
-->
<select id="getUsers5" resultType="user">
select * from t_user
<where>
id in
<foreach collection="list" open="(" separator="," close=")" item="ids">
#{ids}
</foreach>
</where>
</select>
<select id="getUsers6" resultType="user">
select * from t_user
<where>
name in
<foreach collection="list" open="(" separator="," close=")" item="names">
#{names}
</foreach>
</where>
</select>
<!--
trim标签:
-->
<select id="getUsers7" resultType="user">
select * from t_user
<!--
prefix:前缀
prefixOverrides:前缀以什么结束
suffix:后置
suffixOverrides:后置以什么结束
-->
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="name != null and name != ''">
and name like #{name}
</if>
<if test="age > 33">
and age > 33
</if>
</trim>
</select>
<!--
<sql>标签:在外部定义sql语句
<include>标签:在内部引用sql语句
可以拼装成一个完成的sql语句,
一般当sql语句量很大得时候,进行使用
-->
<sql id="select">
select id,name,pwd,age
</sql>
<sql id="from">
from t_user
</sql>
<select id="getUser8" resultType="user">
<include refid="select"/>
<include refid="from"/>
</select>
<update id="updateUser3">
update t_user set
name = #{0},age=#{1}
where id= #{2}
</update>
</mapper>
接口:
public interface UserMapper {
List<User> getUsers(String name);
List<User> getUsers1(User User);
List<User> getUsers2(Map<String, Object> map);
List<User> getUsers3(Map<String, Object> map);
int updateUser(Map<String, Object> map);
int updateUser3(String name,Integer age,Integer id);
}
实现类:
/**
*
* @Description:接口代理
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers(){
//IUserDao userDao = new UserDaoImpl();
/**
* mybatis的通过getMapper来实现自动创建mapper接口的实现类
* mapper.getUsers==》mybatis的session.selectList();
*/
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.getUsers("%张%");
// List<User> users = session.selectList("getUsers","%张%");
for (User user : users) {
System.out.println(user);
}
}
/**
*
* @Description:
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers1(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("%张%");
List<User> users1 = mapper.getUsers1(user);
for (User user2 : users1) {
System.out.println(user2);
}
}
/**
*
* @Description:接口实现修改
* @author mao
* @date 2017年10月30日
*/
@Test
public void updataUser(){
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("name", "陈二狗");
map.put("age", 33);
map.put("id", 100);
int updateUser = mapper.updateUser(map);
System.out.println(updateUser);
session.commit();
}
/**
*
* @Description:传递多个简单类型参数
* 在statement中接收参数使用:参数的下标或者param1
* 参数下边从0开始
* param[args] :[args]使用1开始;例如:param1
* @author mao
* @date 2017年10月30日
*/
@Test
public void updateUser1(){
UserMapper mapper = session.getMapper(UserMapper.class);
int updateUser3 = mapper.updateUser3("田876", 33, 100);
System.out.println(updateUser3);
session.commit();
}
/**
*
*/
@Test
public void getUsers2(){
List<User> selectList = session.selectList("com.bjsxt.mapper.UserMapper.getUsers","%张%");
for (User user : selectList) {
System.out.println(user);
}
}
}
ResultType
映射文件中的statement中的resultType;
resultType:对象类型、简单类型、集合类型
配置文件:
<!--
namespace:相当于包的概念
要保证在一个映射文件中,保证statementid为唯一
-->
<mapper namespace="com.bjsxt.mapper.UserMapper">
<select id="getUsers" resultType="user">
select * from t_user
</select>
<!--resultType返回简单类型 -->
<select id="getUsers1" resultType="int">
select id,name,pwd from t_user
</select>
<!--resultType返回集合类型 -->
<select id="getUsers2" resultType="map">
select id,name,pwd from t_user where name like #{_parameter}
</select>
</mapper>
接口:
public interface UserMapper {
List<User> getUsers();
List<Integer> getUsers1();
List<Map<Object, Object>> getUsers2(String name);
}
实现类:
/**
*
* @Description:resultType返回值为对象类型
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.getUsers();
for (User user : users) {
System.out.println(user);
}
}
/**
*
* @Description:resultType返回简单类型
* 1.在statement中的resultType中设置返回值类型
* 2.在sql语句中 ,如果查询字段有多个,要保证第一个字段与返回值类型一致
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers1(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<Integer> users1 = mapper.getUsers1();
for (Integer integer : users1) {
System.out.println(integer);
}
}
/**
*
* @Description:resultType返回map集合类型
* 1.接口中定义的方法返回值是Map集合
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers2(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<Map<Object, Object>> users2 = mapper.getUsers2("%张%");
for (Map<Object, Object> map : users2) {
System.out.println(map);
}
}