目录
一、动态sql(接SSM框架-MyBatis2中的动态sql)
二、MyBatis的缓存机制
三、数据库中列名和pojo中的实体类不一致问题
四、多表关联查询
一、动态sql(接SSM框架-MyBatis2中的动态sql)
1.<choose><when><otherwise>标签:
(1)单条件查询(只取其一),这是一套标签,功能类似于if…else if…else if…else。
(2)这个标签需要写在<where></where>标签里面。
(3)格式:<choose><when test="条件">sql语句</when> <when test="条件">sql语句</when> <when test="条件">sql语句</when> <otherwise>sql语句</otherwise></choose>。
(4)when中取其中的一个,不会追加多个条件,如果有多个条件,只取最前面的那个,如果都不满足就不查数据了。
2.<set>标签:
(1)用于维护update语句中的set子句,功能如下:
- 满足条件时,会自动添加set关键字;
- 会去除set子句中多余的逗号;
- 不满足条件时,不会生成set关键字;
(2)格式:<set> <if test="username != null and username != ''"> 要修改的列1, </if> <if test="password != null and password != ''"> 要修改的列2, </if> <if test="city != null and city != ''"> 要修改的列3 </if></set>。
(3)set标签里面可以使用if标签完成语句的添加,可以根据不同的条件添加不同的语句。
(4)如果要修改多个数据,要使用逗号隔开。
3.<bind>标签:
(1)用于对数据进行再加工,用于模糊查询,这个加工是在数据使用之前做加工的,加工完之后再去使用。
(2)格式:<bind name="要动态接收的数据名" value="对数据进行加工进行加工" />。
(3)bind标签要写在select标签里面。
4.concat函数:
(1)这个函数在mysql中是用于拼接字符串串的,要拼接多个字符串需要使用逗号分隔。
(2)格式:concat("字符串1","字符串2","字符串3")。
(3)这个函数有点像java中StringBuffer里面的append方法。
5.<foreach>标签:
(1)在一个范围中查询。
(2)用于在SQL语句中遍历集合参数,在in查询中使用。
(3)属性:
- collection:待遍历的集合名称。
- open:设置开始符号。
- separator:项目分隔符。
- close:设置结束符号。
- item:获取到的集合中的单个数据,迭代变量。
- 格式:select * from users where uid in<foreach collection="list" open="(" separator="," close=")" item="i"> #{i}</foreach>。
6.<sql>\\<include>标签:
(1)动态选择要查询的列。
(2)sql标签用于提取SQL语句,include标签用于引用SQL语句。
(3)格式:<sql id="s1"> uid,username</sql> <select id="selChose" resultType="Users"> select <include refid="s1"></include> from users</select>。
(4)注意:include标签是通过id去绑定sql标签的,sql标签可以有多个。
7.案例 (1)映射文件中的内容:
<?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">
<!–关联接口与映射文件–>
<mapper namespace="com.mybatis.mapper.UserMapper">
<!–通过if标签实现动态sql语句–>
<!–where 1=1 是因为我们想要使用and拼接条件,但是where语句必须出现在and前面,所以要把where消耗掉–>
<select id="selAll" resultType="Users">
select * from users where 1 = 1
<if test="uid != 0">
and uid = #{uid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="password != null and password != ''">
and password = #{password}
</if>
<if test="city != null and city != ''">
and city = #{city}
</if>
</select>
<!–解决where问题–>
<select id="selAll2" resultType="Users">
select * from users
<where>
<if test="uid != 0">
and uid = #{uid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="password != null and password != ''">
and password = #{password}
</if>
<if test="city != null and city != ''">
and city = #{city}
</if>
</where>
</select>
<select id="selBy3" resultType="Users">
select * from users
<where>
<choose>
<when test="uid != 0">
uid = #{uid}
</when>
<when test="username != null and username != ''">
username = #{username}
</when>
<otherwise>
city = #{city}
</otherwise>
</choose>
</where>
</select>
<update id="updateBy">
update users
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="city != null and city != ''">
city = #{city}
</if>
</set>
where uid = #{uid}
</update>
<!–方式一–>
<!–bind在数据使用之前做加工处理–>
<select id="selLike" resultType="Users">
<bind name="param1" value="'%' + param1 + '%'"/>
select * from users where city like #{param1}
</select>
<!–方式二 使用函数concat:有点像StringBuffer里面的append方法–>
<select id="selLike2" resultType="Users">
<bind name="param1" value="'%' + param1 + '%'"/>
select * from users where city like concat ('%',#{param1},'%')
</select>
<!–foreach标签中,拼接数据为(4,5,9)
for(Integer i : list){
i代表list集合中的每一个元素
}
–>
<select id="selIn" resultType="Users">
select * from users where uid in
<foreach collection="list" open="(" separator="," close=")" item="i">
#{i}
</foreach>
</select>
<!–根据组合来指定查询列–>
<sql id="s1">
uid,username
</sql>
<sql id="s2">
username,city
</sql>
<select id="selChose" resultType="Users">
select
<include refid="s2"></include>
from users
</select>
</mapper>
(2)接口中的内容:
package com.mybatis.mapper;
import com.mybatis.pojo.Users;
import java.util.List;
public interface UserMapper {
List<Users> selAll(Users user);
List<Users> selAll2(Users user);
List<Users> selBy3(Users user);
int updateBy(Users user);
List<Users> selLike(String city);
List<Users> selLike2(String city);
List<Users> selIn(List<Integer> list);
List<Users> selChose();
}
(3)使用:
package com.mybatis.test;
import com.mybatis.mapper.UserMapper;
import com.mybatis.pojo.Users;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import javax.xml.bind.annotation.XmlAnyAttribute;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Demo {
SqlSession session;
UserMapper mapper;
public Demo(){
//加载application-dao.xml
String resource = "application-dao.xml";
try {
//将文件转换为流对象
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获取发送sql语句的对象
session = sqlSessionFactory.openSession();
//获取接口对象
mapper = session.getMapper(UserMapper.class);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 查询
*/
@Test
public void selAll(){
Users u = new Users();
// u.setUid(22);
// u.setUsername("小乔");
// u.setPassword("123321");
u.setCity("江南");
List<Users> users = mapper.selAll(u);
for (Users user : users) {
System.out.println(user);
}
}
@Test
public void selAll2(){
Users u = new Users();
// u.setUid(22);
u.setUsername("小乔");
u.setPassword("123321");
// u.setCity("江南");
List<Users> users = mapper.selAll2(u);
for (Users user : users) {
System.out.println(user);
}
}
@Test
public void selBy3(){
Users u = new Users();
// u.setUid(22);
// u.setUsername("小乔");
// u.setCity("江南");
List<Users> users = mapper.selBy3(u);
for (Users user : users) {
System.out.println(user);
}
}
@Test
public void update(){
Users u = new Users();
u.setUid(26);
// u.setPassword("123");
// u.setCity("重庆");
u.setUsername("夏蝉");
int n = mapper.updateBy(u);
System.out.println(n == 1 ? "修改成功" : "修改失败");
session.commit();
}
@Test
public void like(){
// List<Users> users = mapper.selLike("江");
List<Users> users = mapper.selLike2("江");
for (Users user : users) {
System.out.println(user);
}
}
@Test
public void selIn(){
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(5);
list.add(9);
List<Users> users = mapper.selIn(list);
for (Users user : users) {
System.out.println(user);
}
}
@Test
public void selChose(){
List<Users> users = mapper.selChose();
for (Users user : users) {
System.out.println(user);
}
}
}
二、MyBatis的缓存机制
1.缓存就是用户在第一次访问某些数据的时候,会将这些数据缓存到redis中,如果要再次访问这些内容,可以直接从redis中读取,而不需要在去访问数据库了。
2.redis可以看作是一个基于内存的数据库,而mysql可以看作是基于硬盘的数据库。
3.缓存的作用:
(1)缓存用于提高查询的效率。
(2)MyBatis的缓存是使用SQL标签的ID作为缓存的唯一标识的,执行相同的标签可以使用缓存,不同的标签不能使用缓存。
(3)MyBatis中有两种缓存机制,一个是一级缓存,一个是二级缓存。
4.一级缓存:
(1)默认开启线程级别的缓存,SqlSession的缓存。
(2)在一个SqlSession生命周期中有效,SqlSession关闭,缓存清空。
5.二级缓存:
(1)进程级别的缓存,SqlSessionFactory的缓存。
(2)在一个SqlSessionFactory生命周期中有效,可以在多个SqlSession生命周期中共享。
(3)默认关闭,需要使用的时候,要为某个命名空间开启二级缓存(在mapper.xml中配置<cache>):
- 在application-dao.xml配置文件中加<setting name="cacheEnabled" value="true"/>,这个也可以不加。
- 在mapper.xml中第一行加<cache></cache>。
- 注意:在application-dao.xml配置文件中加的配置,现在可以不加,但是在老版本之中是需要添加的,在新版本中可以直接在mapper.xml中添加标签就可以了。
三、数据库中列名和pojo中的实体类不一致问题
1.如果查询时使用resultType属性,表示采用MyBatis的Auto-Mapping(自动映射)机制,即相同的列名和属性名会自动匹配。因此,当数据库表的列名和类的属性名不一致时,会导致查不到数据。解决该问题有两种方式:一种是列别名,一种是使用resultMap手动映射。
2.列别名:
(1)查询时,可以通过列别名的方式将列名和属性名保持一致,继续使用自动映射,从而解决该问题,但是较为麻烦。
3.resultMap手动映射:
(1)将resultType换成resultMap
- resultMap用于自定义映射关系,可以由程序员自主制定列名和属性名的映射关系。一但使用resultMap,表示不在采用自动映射机制。
(2)在sql语句对应的标签外面加一个resultMap标签。
(3)格式:
- resultMap标签:
- <resultMap id="mm" type="com.mybatis.pojo.Users2">
<id property="id" column="uid"></id>
<result property="uname" column="username"></result>
<result property="pwd" column="password"></result>
<result property="cite" column="city"></result>
</resultMap> - sql语句标签:
- <select id="selAllUsers" resultMap="mm">
select * from users
</select> - 注意:
- 这两个通过id和resultMap关联起来,其中id标签和result标签效果是一样的,id标签只是为了区分是否是主键。
- resultMap标签中的子标签内的属性property代表的是实体的中的属性,而column属性代表的是数据库中的列名。
四、多表关联查询
1.多表关联查询在MyBatis中可以有两种方式实现:一种是关联的方式,一种是装配的方式。
2.关联实现多表查询:
(1)关联的方式就是将sql语句完整的放入映射文件中,然后动态取值查询就可以了。
3.手动装配实现多表查询(多对一):
(1)mapper层只做单表查询操作,在service层进行手动装配,实现关联查询的结果。
(2)在application中关联映射文件的时候,如果有多个映射文件,一个一个关联太麻烦了,可以使用<package>标签:
- 格式:<package name="映射文件所在的包名.*"/>。
- 这种方式可以关联一个包下面的所有映射文件。
- 案例:
- <mappers>
<!–关联外部写有sql语句的映射文件
<mapper resource="com/mybatis/mapper/StudentMapper.xml"/>
<mapper resource="com/mybatis/mapper/ClazzMapper.xml"/>
–>
<package name="com.mybatis.mapper.*"/>
</mappers>
(3)手动装配就是先将一个表中的数据查处理,在根据这个表中关联的外键去查询另一张表中的内容,这样两张表中的内容就都查到了。
(4)手动装配其实就是把多表查询拆分成单表查询。如果是多对一查询,就先把多的一方查出来,在用多把一查出来。如果是一对多,就先把一查出来,再去查询多。
(5)简单来说,手动装配可以理解为手动组装,把你要的多个关联起来的数据先拆分成单个数据进行查询,最后将查询的结果在手动组装起来,这个称之为业务装配。
(6)注意:这种关联查询需要我们在实体类中将数据关联起来,比如多对一,那么我们就要使用多去持有一,就像多个学生对应一个班级,那么我们就要将班级的实体类当作学生的实体类是属性。
(7)案例:
- ClazzMapper.xml映射文件中的内容:
- <?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">
<!–关联接口与映射文件–>
<mapper namespace="com.mybatis.mapper.ClazzMapper">
<select id="selByCid" resultType="Clazz">
select * from clazz where cid = #{param1}
</select>
</mapper> - ClazzMapper接口中的内容:
- package com.mybatis.mapper;
import com.mybatis.pojo.Clazz;
public interface ClazzMapper {
Clazz selByCid(int cid);
} - StudentMapper.xml映射文件中的内容:
- <?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">
<!–关联接口与映射文件–>
<mapper namespace="com.mybatis.mapper.StudentMapper">
<select id="selAll" resultType="Student">
select * from student
</select>
</mapper> - StudentMapper接口中的内容:
- package com.mybatis.mapper;
import com.mybatis.pojo.Student;
import java.util.List;
public interface StudentMapper {
List<Student> selAll();
} - 具体使用:
- package com.mybatis.test;
import com.mybatis.mapper.ClazzMapper;
import com.mybatis.mapper.StudentMapper;
import com.mybatis.pojo.Clazz;
import com.mybatis.pojo.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class Demo {
SqlSession session;
ClazzMapper clazzMapper;
StudentMapper studentMapper;
public Demo(){
//加载application-dao.xml
String resource = "application-dao.xml";
try {
//将文件转换为流对象
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
//获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//获取发送sql语句的对象
session = sqlSessionFactory.openSession();
//获取接口对象
clazzMapper = this.session.getMapper(ClazzMapper.class);
studentMapper = this.session.getMapper(StudentMapper.class);
} catch (IOException e) {
e.printStackTrace();
}
}/**
* 查询学生及其所在的班级信息(多对一 查询)
* 手动装配
*/
@Test
public void selAll(){
List<Student> students = studentMapper.selAll();
for (Student stu : students) {
//学生对应的班级cid
int cid = stu.getCid();
//根据cid查询它所在的班级
Clazz clazz = clazzMapper.selByCid(cid);
stu.setClazz(clazz);
}
for (Student stu : students) {
System.out.println(stu.getSid() + "-" + stu.getSname() + "-" + stu.getAge() + "-" + stu.getCid() + "-" + stu.getClazz());
}
}
}
网硕互联帮助中心


评论前必须登录!
注册