七、 动态 SQL
在 MyBatis 中提供了动态 SQL 功能。将使用 Java 代码拼接 SQL 语句,改变为在 XML 映射文件中使用标签拼接 SQL 语句。
MyBatis 中动态 SQL 是编写在 mapper.xml 中的,其语法和 JSTL 类似,但是却是基于强大 的 OGNL 表达式实现的。
1 if 标签
if 标签单分支判断语句
1.1修改映射配置文件
<!-- 根据用户给定的条件进行查询-->
<select id="selectUsersByProperty" resultType="users">
select * from users where 1=1
<if test="userid != 0">
and userid = #{userid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="usersex != null and usersex != ''">
and usersex = #{usersex}
</if>
</select>
1.2修改 UsersMapper 接口
List<Users> selectUsersByProperty(Users users);
1.3创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByPropertyTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("itbz-sxt4");
users.setUserid(13);
List<Users> list = usersMapper.selectUsersByProperty(users);
list.forEach(System.out::println);
}
}
2 choose、when、otherwise 标签
从多个条件中选择一个使用。
2.1修改映射配置文件
<!--多选一条件-->
<select id="selectUsersByChoose" resultType="users">
select * from users where 1=1
<choose>
<when test="username != null and username != ''">
and username = #{username}
</when>
<when test="usersex != null and usersex != ''">
and usersex = #{usersex}
</when>
<otherwise>
and userid = 1
</otherwise>
</choose>
</select>
2.2修改 UsersMapper 接口
List<Users> selectUsersByChoose(Users users);
2.3创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByChooseTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("itbz-sxt4");
users.setUsersex("male");
List<Users> list = usersMapper.selectUsersByChoose(users);
list.forEach(System.out::println);
}
}
3 where 标签
使用 where 标签,就不需要提供 where 1=1 这样的条件了。如果判断条件不为空则自 动添加 where 关键字,并且会自动去掉第一个条件前面的 and 或 or。
3.1修改映射配置文件
<!-- 根据用户给定的条件进行查询使用where标签实现-->
<select id="selectUsersByPropertyWhere" resultType="users">
select * from users
<where>
<if test="userid != 0">
and userid = #{userid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="usersex != null and usersex != ''">
and usersex = #{usersex}
</if>
</where>
</select>
3.2修改 UsersMapper 接口
List<Users> selectUsersByPropertyWhere(Users users);
3.3创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByPropertyWhereTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("itbz-sxt4");
users.setUserid(14);
List<Users> list = usersMapper.selectUsersByPropertyWhere(users);
list.forEach(System.out::println);
}
}
4 bind 标签
bind 标签允许我们在 OGNL 表达式以外创建一个变量,并可以将其绑定到当前的 SQL 语句中。一般应用于模糊查询,通过 bind 绑定通配符和查询值。
4.1修改映射配置文件
<!--根据用户姓名模糊查询-->
<select id="selectUsersByLikeName" resultType="users">
<bind name="likeName" value="'%'+name+'%'"/>
select * from users where username like #{likeName}
<!-- select * from users where username like concat('%',#{name},'%') -->
</select>
4.2修改 UsersMapper 接口
List<Users> selectUsersByLikeName(String name);
4.3创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByLikeNameTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
List<Users> list = usersMapper.selectUsersByLikeName("a");
list.forEach(System.out::println);
}
}
5 set 标签
set 标签用在 update 语句中。借助 if 标签,可以只对有具体值的字段进行更新。set 标 签会自动添加 set 关键字,自动去掉最后一个 if 语句的多余的逗号。
5.1修改映射配置文件
<!-- 选择更新-->
<update id="usersUpdate">
update users
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="usersex != null and usersex != ''">
usersex = #{usersex},
</if>
</set>
where userid = #{userid}
</update>
5.2修改 UsersMapper 接口
void usersUpdate(Users users);
5.3创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class UsersUsersTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("oldlu");
users.setUsersex("male");
users.setUserid(2);
usersMapper.usersUpdate(users);
sqlSession.commit();
}
}
6 foreach 标签
foreach 标签的功能非常强大,我们可以将任何可迭代对象如 List、Set 、Map 或者数 组对象作为集合参数传递给 foreach 标签进行遍历。它也允许我们指定开头与结尾的字符串 以及集合项迭代之间的分隔符。
6.1迭代 List、Set
类型:
collection=”collection”
名称:
void example(@Param(“suibian”) List list)
void example(@Param(“suibian”) Set set)
collection=”suibian”
6.1.1 修改映射配置文件
<!--查询用户ID为1或者2的用户-->
<select id="selectUsersByIdUseCollection" resultType="users">
select * from users where userid in
<foreach collection="collection" item="userid" open="(" separator="," close=")">
#{userid}
</foreach>
</select>
6.1.2 修改 UsersMapper 接口
List<Users> selectUsersByIdUseCollection(Collection collection);
6.1.3 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.omg.PortableInterceptor.INACTIVE;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class SelectUsersByIdUseCollectionTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
/*List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);*/
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
List<Users> users = usersMapper.selectUsersByIdUseCollection(set);
users.forEach(System.out::println);
}
}
6.2迭代数组
类型:
collection=”array”
名称:
void example(@Param(“suibian”) int[] arr)
collection=”suibian”
6.2.1 修改映射配置文件
<!--查询用户ID为1或者2的用户使用数组传递参数-->
<select id="selectUsersByIdUseArray" resultType="users">
select * from users where userid in
<foreach collection="array" item="userid" open="(" separator="," close=")">
#{userid}
</foreach>
</select>
6.2.2 修改 UsersMapper 接口
List<Users> selectUsersByIdUseArray(int[] arr);
6.2.3 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class SelectUsersByIdUseArrayTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
int[] arr = new int[]{
1,2};
List<Users> users = usersMapper.selectUsersByIdUseArray(arr);
users.forEach(System.out::println);
}
}
6.3迭代 Map
名称:
void example(@Param(“suibian”) Map map)
collection=”suibian”或者 collection=”suibian.entrySet()”
6.3.1 修改映射配置文件
<!--根据给定的条件做计数处理-->
<!-- select count(*) from users where username = 'itbz-sxt4' and usersex = 'male'-->
<select id="selectUsersCount" resultType="int">
select count(*) from users where
<foreach collection="suibian" separator="and" item="value" index="key">
${key} = #{value}
</foreach>
</select>
6.3.2 修改 UsersMapper 接口
int selectUsersCount(@Param("suibian") Map<String,String> map);
6.3.3 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.HashMap;
import java.util.Map;
public class SelectUsersCountTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Map<String,String> map= new HashMap<>();
map.put("username","itbz-sxt4");
map.put("usersex","male");
int count = usersMapper.selectUsersCount(map);
System.out.println(count);
}
}
6.4使用 foreach 标签完成批量添加
6.4.1 修改映射配置文件
<!--批量添加用户-->
<!--insert into users values(DEFAULT,'itbz-sxt5','male'),(DEFAULT,'itbz-sxt6','male')-->
<insert id="insertUsersBatch" >
insert into users values
<foreach collection="collection" item="user" separator=",">
(default ,#{user.username},#{user.usersex})
</foreach>
</insert>
6.4.2 修改 UsersMapper 接口
int insertUsersBatch(List<Users> list);
6.4.3 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.ArrayList;
import java.util.List;
public class InsertUsersBatchTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
List<Users> list = new ArrayList<>();
Users users = new Users();
users.setUsername("sxt6");
users.setUsersex("male");
Users users1 = new Users();
users1.setUsername("sxt7");
users1.setUsersex("male");
list.add(users);
list.add(users1);
int flag = usersMapper.insertUsersBatch(list);
sqlSession.commit();
System.out.println(flag);
}
}
八、 Mybatis 缓存
缓存是一般的 ORM 框架都会提供的功能,目的就是提升查询的效率和减少数据库的压力,缓存的重要性是不言而喻的。Mybatis 会将相同查询条件的 SQL 语句的查询结果存储在 内存或者某种缓存介质当中,当下次遇到相同的查询 SQL 时候不在执行该 SQL,而是直接从 缓存中获取结果,减少服务器的压力,尤其是在查询越多、缓存命中率越高的情况下,使用 缓存对性能的提高更明显。
MyBatis 缓存方式分为一级缓存和二级缓存,同时也可配置关于缓存设置。
一级缓存是将结果缓存在 SqlSession 对象中,二级缓存是存储在 SqlSessionFactory 对象 中。默认情况下,MyBatis 开启一级缓存,没有开启二级缓存。
当数据量大的时候可以借助一些第三方缓存技术来协助保存 Mybatis 的二级缓存数据。
1 一级缓存的使用
一级缓存也叫本地缓存,MyBatis 的一级缓存是在会话(SqlSession)层面进行缓存的。 MyBatis 的一级缓存是默认开启的,不需要任何的配置。
1.1一级缓存的生命周期
- MyBatis 在开启一个数据库会话时,会创建一个新的 SqlSession 对象,SqlSession 对象中 会有一个新的 Executor 对象。Executor 对象中持有一个新的 PerpetualCache 对象;当会 话结束时,SqlSession 对象及其内部的 Executor 对象还有 PerpetualCache 对象也一并释 放掉。
- 如果 SqlSession 调用了 close()方法,会释放掉一级缓存 PerpetualCache 对象,一级缓存 将不可用。
- 如果 SqlSession 调用了 clearCache(),会清空 PerpetualCache 对象中的数据,但是该对象 仍可使用。
- SqlSession 中执行了任何一个 update 操作(update()、delete()、insert()) ,都会清空 PerpetualCache 对象的数据,但是该对象可以继续使用。
1.2如何判断两次查询是完全相同的查询
Mybatis 认为,对于两次查询,如果以下条件都完全一样,那么就认为它们是完全相同 的两次查询。
- 传入的 statementId。
- 查询时要求的结果集中的结果范围。
- 这次查询所产生的最终要传递给 Preparedstatement 的 Sql 语句字符串。
- 传递的参数值
1.3测试一级缓存
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class SelectUsersByIdCacheOneTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersById(1);
System.out.println(users);
Users users2 = new Users();
users2.setUsername("aaaa");
users2.setUsersex("male");
usersMapper.insertUsers(users);
System.out.println("-----------------");
Users users1 = usersMapper.selectUsersById(1);
System.out.println(users1);
}
}
2 二级缓存的使用
MyBatis 的二级缓存是 Application 级别的缓存,它可以提高对数据库查询的效率,以提 高应用的性能。二级缓存是 SqlSessionFactory 上的缓存,可以是由一个 SqlSessionFactory 创 建的不同的 SqlSession 之间共享缓存数据。默认并不开启。
SqlSession 在执行 commit()或者 close()的时候将数据放入到二级缓存。
Sqlsession 共享二级缓存
2.1二级缓存的配置方式
二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis 要求缓存的 POJO 必须 是可序列化的, 也就是要求实现 Serializable 接口。在映射配置文件中配置<cache/>
就可以 开启缓存了。
2.2二级缓存特点
- 映射语句文件中的所有 select 语句将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 二级缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响
- 如果在加入标签的前提下让个别 select 元素不使用缓存,可以使用 useCache 属性,设置为 false。
- 缓存会使用默认的 Least Recently Used(LRU,最近最少使用的)算法来收回。
- 根据时间表,比如 No Flush Interval,(CNFI 没有刷新间隔),缓存不会以任何时间顺序 来刷新。
- 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用
- 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以 安全的被调用者修改,不干扰其他调用者或线程所做的潜在修改。
2.3cache 标签的可选属性
2.4测试二级缓存
2.4.1 配置 cacheEnabled
在 mybatis-config.xml 文件中的<settings>
标签配置开启二级缓存。cacheEnabled 的默认 值就是 true,所以这步的设置可以省略。
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
2.4.2 在映射配置文件中添加
<mapper namespace="com.bjsxt.mapper.UsersMapper">
<cache/>
</mapper>
2.4.3 JavaBean 对象必须实现序列化接口
public class Users implements Serializable{
}
2.4.4 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class SelectUsersByIdCacheTwoTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersById(1);
System.out.println(users);
MybatisUtils.closeSqlSession();
System.out.println("-----------------------");
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
UsersMapper usersMapper1 = sqlSession1.getMapper(UsersMapper.class);
Users users1 = usersMapper1.selectUsersById(1);
System.out.println(users1);
}
}
2.4.5 测试结果
九、 Mybatis 的多表关联查询
1 搭建环境
1.1创建项目
1.2添加 jar 包
1.3创建实体
package com.bjsxt.pojo;
import java.util.List;
public class Users {
private int userid;
private String username;
private String usersex;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsersex() {
return usersex;
}
public void setUsersex(String usersex) {
this.usersex = usersex;
}
@Override
public String toString() {
return "Users{" +
"userid=" + userid +
", username='" + username + '\'' +
", usersex='" + usersex + '\'' +
'}';
}
}
1.4创建 properties 文件
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjsxt
jdbc.username=root
jdbc.password=root
log4j.properties
log4j.rootLogger=debug,console
### appender.console输出到控制台 ###
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=<%d> %5p (%F:%L) [%t] (%c) - %m%n
log4j.appender.console.Target=System.out
### appender.logfile输出到日志文件 ###
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=SysLog.log
log4j.appender.logfile.MaxFileSize=500KB
log4j.appender.logfile.MaxBackupIndex=7
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=<%d> %p (%F:%L) [%t] %c - %m%n
1.5添加工具类
package com.bjsxt.utils;
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 java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
private static SqlSessionFactory sqlSessionFactory = null;
static{
//创建SqlSessionFactory
InputStream is = null;
try{
is = Resources.getResourceAsStream("mybatis-cfg.xml");
}catch (IOException e){
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
//获取SqlSession
public static SqlSession getSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession == null){
sqlSession = sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
//关闭SqlSession
public static void closeSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession != null){
sqlSession.close();
threadLocal.set(null);
}
}
}
1.6创建全局配置文件
<?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>
<!--引入properties属性文件-->
<properties resource="db.properties"/>
<settings>
<setting name="lazyLoadTriggerMethods" value=""/>
</settings>
<!--配置别名-->
<typeAliases>
<package name="com.bjsxt.pojo"/>
</typeAliases>
<!--配置环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射配置文件-->
<mappers>
<package name="com.bjsxt.mapper"/>
</mappers>
</configuration>
1.7创建映射配置文件
<?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.bjsxt.mapper.UsersMapper">
</mapper>
2 手动处理映射关系
resultMap 标签是 Mybatis 最强大的元素,它可以将查询到的复杂数据(比如查询到几个表 中数据)映射到一个结果集当中。
2.1 resultMap 的基础使用场景
在 Mybatis 中如果查询的结果集的列名与 POJO 的属性名相同,那么我们是不需要在 Mybatis 中配置映射关系的,但是当查询到的结果集的列名与 POJO 的属性名不匹配时, Mybatis 是无法完成影射处理的。
解决方案:
- 通过定义列别名的方式来解决该问题。
- 通过在 resultMap 标签中定义映射关系来解决该问题。
2.2 通过 resultMap 标签解决实体与结果集的映射
2.2.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.bjsxt.mapper.UsersMapper">
<resultMap id="usersMapper" type="com.bjsxt.pojo.Users">
<id property="userid" column="id"/>
<result property="username" column="name"/>
<result property="usersex" column="sex"/>
</resultMap>
<select id="selectUsersAll" resultMap="usersMapper">
select userid as id ,username as name ,usersex as sex from users
</select>
</mapper>
2.2.2 修改 UsersMapper 接口
List<Users> selectUsersAll();
2.2.3 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersAllTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
List<Users> list = usersMapper.selectUsersAll();
list.forEach(System.out::println);
}
}
3 一对一的关联查询
3.1 <association>
标签
<association>
标签是处理单一的关联对象(处理单一属性的关联关系)。
property
:指定关联对象的属性
javaType
:关联对象的类型(可以省略)
select
:执行一个新的查询
column
:在新的查询中用哪个列的值作为查询条件
3.2需求
完成用户与角色查询。要求一个用户只能对应一个角色。
3.3创建 roles 表
CREATE TABLE `roles` (
`roleid` int(11) NOT NULL AUTO_INCREMENT,
`rolename` varchar(30) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`roleid`),
UNIQUE KEY `roles_fk` (`user_id`) USING BTREE,
CONSTRAINT `roles_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.4创建 Roles 实体
package com.bjsxt.pojo;
public class Roles {
private int roleid;
private String rolename;
public int getRoleid() {
return roleid;
}
public void setRoleid(int roleid) {
this.roleid = roleid;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
@Override
public String toString() {
return "Roles{" +
"roleid=" + roleid +
", rolename='" + rolename + '\'' +
'}';
}
}
3.5修改 Users 实体
package com.bjsxt.pojo;
import java.util.List;
public class Users {
private int userid;
private String username;
private String usersex;
private Roles roles;
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsersex() {
return usersex;
}
public void setUsersex(String usersex) {
this.usersex = usersex;
}
@Override
public String toString() {
return "Users{" +
"userid=" + userid +
", username='" + username + '\'' +
", usersex='" + usersex + '\'' +
'}';
}
}
3.6修改映射配置文件
<!--一对一的关联查询映射-->
<resultMap id="usersAndRolesMapper" type="com.bjsxt.pojo.Users">
<id property="userid" column="userid"/>
<result property="username" column="username"/>
<result property="usersex" column="usersex"/>
<association property="roles" javaType="com.bjsxt.pojo.Roles">
<id property="roleid" column="roleid"/>
<result property="rolename" column="rolename"/>
</association>
</resultMap>
<!--根据用户ID查询用户与角色-->
<select id="selectUsersAndRoles" resultMap="usersAndRolesMapper">
select * from users as u ,roles as r where u.userid = r.user_id and u.userid = #{userid}
</select>
3.7修改 UsersMapper 接口
Users selectUsersAndRoles(int userid);
3.8创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Roles;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class SelectUsersAndRolesTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersAndRoles(1);
System.out.println(users);
Roles roles = users.getRoles();
System.out.println(roles);
}
}
4 一对多的关联查询
4.1<collection>
标签
<collection>
标签是处理所关联对象是多个的(处理关联属性是集合时的关联关系)。
property
:指定关联对象的属性
javaType
:关联对象的类型(可以省略。默认为 List 类型,如果集合是 Set 类型时需要配置并给定 Set 的全名)
ofType
:指定集合里存放的对象类型
select
:执行一个新的查询
column
:在新的查询中用哪个列的值作为查询条件
4.2需求
完成用户与订单查询。要求一个用户可以对应多个订单。
4.3创建 Orders 表
CREATE TABLE `orders` (
`orderid` int(11) NOT NULL AUTO_INCREMENT,
`orderprice` double DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`orderid`),
KEY `orders_fk` (`user_id`),
CONSTRAINT `orders_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
4.4创建 Orders 实体
package com.bjsxt.pojo;
import java.util.List;
public class Orders {
private int orderid;
private double orderprice;
public int getOrderid() {
return orderid;
}
public void setOrderid(int orderid) {
this.orderid = orderid;
}
public double getOrderprice() {
return orderprice;
}
public void setOrderprice(double orderprice) {
this.orderprice = orderprice;
}
@Override
public String toString() {
return "Orders{" +
"orderid=" + orderid +
", orderprice=" + orderprice +
'}';
}
}
4.5修改 Users 实体
package com.bjsxt.pojo;
import java.util.List;
public class Users {
private int userid;
private String username;
private String usersex;
private Roles roles;
private List<Orders> orders;
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsersex() {
return usersex;
}
public void setUsersex(String usersex) {
this.usersex = usersex;
}
@Override
public String toString() {
return "Users{" +
"userid=" + userid +
", username='" + username + '\'' +
", usersex='" + usersex + '\'' +
'}';
}
}
4.6修改映射配置文件
<!--一对多映射关系-->
<resultMap id="usersAndOrdersMapper" type="com.bjsxt.pojo.Users">
<id property="userid" column="userid"/>
<result property="username" column="username"/>
<result property="usersex" column="usersex"/>
<collection property="orders" ofType="com.bjsxt.pojo.Orders">
<id property="orderid" column="orderid"/>
<result property="orderprice" column="orderprice"/>
</collection>
</resultMap>
<!--根据用户ID查询用户以及该用户所对应的所有订单-->
<select id="selectUsersAndOrders" resultMap="usersAndOrdersMapper">
select * from users as u ,orders as o where u.userid = o.user_id and u.userid = #{userid}
</select>
4.7修改 UsersMapper 接口
Users selectUsersAndOrders(int userid);
4.8创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Orders;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersAndOrdersTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersAndOrders(1);
System.out.println(users);
List<Orders> list = users.getOrders();
list.forEach(System.out::println);
}
}
5 多对多的关联查询
5.1需求
根据 ID 查询用户与订单以及订单中所包含的所有商品。
5.2创建 items 表
CREATE TABLE `items` (
`itemid` int(11) NOT NULL AUTO_INCREMENT,
`itemname` varchar(255) DEFAULT NULL,
`itemprice` double DEFAULT NULL,
PRIMARY KEY (`itemid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
5.3创建 orders_items 中间表
CREATE TABLE `orders_items` (
`order_id` int(11) NOT NULL,
`item_id` int(11) NOT NULL,
PRIMARY KEY (`order_id`,`item_id`),
KEY `order_item_fk2` (`item_id`),
CONSTRAINT `order_item_fk1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`orderid`),
CONSTRAINT `order_item_fk2` FOREIGN KEY (`item_id`) REFERENCES `items` (`itemid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
5.4创建 Items 实体
package com.bjsxt.pojo;
public class Items {
private int itemid;
private String itemname;
private double itemprice;
public int getItemid() {
return itemid;
}
public void setItemid(int itemid) {
this.itemid = itemid;
}
public String getItemname() {
return itemname;
}
public void setItemname(String itemname) {
this.itemname = itemname;
}
public double getItemprice() {
return itemprice;
}
public void setItemprice(double itemprice) {
this.itemprice = itemprice;
}
@Override
public String toString() {
return "Items{" +
"itemid=" + itemid +
", itemname='" + itemname + '\'' +
", itemprice=" + itemprice +
'}';
}
}
5.5修改 Orders 实体
package com.bjsxt.pojo;
import java.util.List;
public class Orders {
private int orderid;
private double orderprice;
private List<Items> items;
public List<Items> getItems() {
return items;
}
public void setItems(List<Items> items) {
this.items = items;
}
public int getOrderid() {
return orderid;
}
public void setOrderid(int orderid) {
this.orderid = orderid;
}
public double getOrderprice() {
return orderprice;
}
public void setOrderprice(double orderprice) {
this.orderprice = orderprice;
}
@Override
public String toString() {
return "Orders{" +
"orderid=" + orderid +
", orderprice=" + orderprice +
'}';
}
}
5.6修改映射配置文件
<!--多对多关联查询-->
<resultMap id="usersAndOrdersAndItems" type="com.bjsxt.pojo.Users">
<id property="userid" column="userid"/>
<result property="username" column="username"/>
<result property="usersex" column="usersex"/>
<collection property="orders" ofType="com.bjsxt.pojo.Orders">
<id property="orderid" column="orderid"/>
<result property="orderprice" column="orderprice"/>
<collection property="items" ofType="com.bjsxt.pojo.Items">
<id property="itemid" column="itemid"/>
<result property="itemid" column="itemid"/>
<result property="itemname" column="itemname"/>
<result property="itemprice" column="itemprice"/>
</collection>
</collection>
</resultMap>
<!--根据用户ID查询用户与订单以及订单中所包含的商品-->
<select id="selectUsersAndOrdersAndItems" resultMap="usersAndOrdersAndItems">
select * from users as u,orders as o, orders_items as oi ,items as i where u.userid = o.user_id and o.orderid = oi.order_id and oi.item_id = i.itemid and u.userid = #{userid}
</select>
5.7修改 UsersMapper 接口
Users selectUsersAndOrdersAndItems(int userid);
5.8创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Items;
import com.bjsxt.pojo.Orders;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersAndOrdersAndItemsTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersAndOrdersAndyItems(1);
System.out.println(users);
List<Orders> orders = users.getOrders();
for(Orders order:orders){
System.out.println(order);
List<Items> item = order.getItems();
item.forEach(System.out::println);
}
}
}
6 Mybatis 多表查询中的数据加载方式
6.1多表查询 SQL 语句的写法
6.1.1 连接查询
使用内连接或者外连接的方式查询数据。
优点:在一次查询中完成数据的查询操作。降低查询次数提高查询效率。
缺点:如果查询返回的结果集较多会消耗内存空间。
6.1.2 N+1 次查询
分解式查询,将查询分解成多个 SQL 语句。
优点:配和着延迟加载可实现结果集分步获取,节省内存空间。
缺点:由于需要执行多次查询,相比连接查询效率低。
6.2 N+1 查询的加载方式
6.2.1 立即加载
在一次查询中执行所有的 SQL 语句。
6.2.2 延迟加载
在一次查询中执行部分 SQL 语句,根据操作映射的关联象触发其他查询。
6.3 MyBatis 的延迟加载的使用
在 Mybatis 中可以使用延迟加载数据的策略实现对关联对象的查询。 使用延迟加载要求:
- 查询方式需要使用 N+1 次查询。
- 在映射配置文件或者全局配置文件中开启延迟加载。
6.3.1 开启延迟加载
开启延迟加载方式:
- 在
<association>
、<collection>
标签中通过fetchType
属性开启延迟加载,仅针对当前标签 生效。fectType:lazy
开启延迟加载,fectType:eager
开启立即加载。通过select
属性指定 需要执行的查询的 ID。通过column
属性指定将封装查询结果对象的哪个属性的值作为下一个查询的查询条件。 - 在全局配置文件中的
<settings>
标签中开启延迟加载,所有的association
和collection
元 素都生效。<setting name="lazyLoadingEnabled" value="true"/>
- 配置触发加载方法,
lazyLoadTriggerMethods
:指定实体对象的哪个方法触发一次加载。
6.3.2 修改全局配置文件配置触发方法
<settings>
<setting name="lazyLoadTriggerMethods" value=""/>
</settings>
6.3.3 修改映射配置文件
<!--延迟加载-->
<resultMap id="usersAndOrdersMapperLazy" type="com.bjsxt.pojo.Users">
<id property="userid" column="userid"/>
<result property="username" column="username"/>
<result property="usersex" column="usersex"/>
<collection property="orders" ofType="com.bjsxt.pojo.Orders" fetchType="lazy" select="selectOrdersByUserId" column="userid"/>
</resultMap>
<!--根据用户ID查询用户-->
<select id="selectUsersByIdLazy" resultMap="usersAndOrdersMapperLazy">
select * from users where userid = #{userid}
</select>
<!--根据用户ID查询订单-->
<select id="selectOrdersByUserId" resultType="com.bjsxt.pojo.Orders">
select * from orders where user_id = #{userid}
</select>
6.3.4 修改 UsersMapper 接口
Users selectUsersByIdLazy(int userid);
6.3.5 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Orders;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByIdLazyTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersByIdLazy(1);
System.out.println(users);
List<Orders> list = users.getOrders();
list.forEach(System.out::println);
}
}
十、 Mybatis 注解的使用
在 Mybatis 中如果使用注解式开发,那么注解需要添加在 Mapper 接口中的抽象方法上, 在注解中给定需要执行的 SQL 语句即可,这样就可以不需要映射配置文件。MyBatis 支持纯 注解方式,支持纯映射配置文件方式,也支持注解和映射配置文件混合形式。当只有接口没 有映射配置文件时在 mybatis-cfg.xml 中对于引入映射可以通过<mapper class=””></mapper>
加载指定接口类。也可以使用<package name=””/>
指定加载的包。
1 使用注解完成查询
1.1查询所有用户
1.1.1 修改 UsersMapper 接口
package com.bjsxt.mapper;
import com.bjsxt.pojo.Users;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
import java.util.Map;
public interface UsersMapper {
@Select("select * from users")
List<Users> selectUsersAll();
}
1.1.2 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersAllTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
List<Users> list = usersMapper.selectUsersAll();
list.forEach(System.out::println);
}
}
1.2注解式开发时的参数传递
1.2.1 顺序传参法
@Select("select * from users where username = #{param1} and usersex = #{param2}")
List<Users> selectUsersByNameAndSexOrder(String username,String usersex);
@Select("select * from users where username = #{name} and usersex = #{sex}")
List<Users> selectUsersByNameAndSexOrder2(@Param("name") String username,@Param("sex") String usersex);
添加测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByNameAndSexOrderTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
List<Users> list = usersMapper.selectUsersByNameAndSexOrder("oldlu","male");
list.forEach(System.out::println);
}
}
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByNameAndSexOrder2Test {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
List<Users> list = usersMapper.selectUsersByNameAndSexOrder2("oldlu","male");
list.forEach(System.out::println);
}
}
1.2.2 POJO 传参法
@Select("select * from users where username = #{username} and usersex = #{usersex}")
List<Users> selectUsersByNameAndSexPOJO(Users users);
添加测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByNameAndSexPOJOTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("oldlu");
users.setUsersex("male");
List<Users> list = usersMapper.selectUsersByNameAndSexPOJO(users);
list.forEach(System.out::println);
}
}
1.2.3 Map 传参法
@Select("select * from users where username = #{keyname} and usersex = #{keysex}")
List<Users> selectUsersByNameAndSexMap(Map<String,String> map);
添加测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SelectUsersByNameAndSexMapTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Map<String,String> map = new HashMap<>();
map.put("keyname","oldlu");
map.put("keysex","male");
List<Users> list = usersMapper.selectUsersByNameAndSexMap(map);
list.forEach(System.out::println);
}
}
2 使用注解完成 DML 操作
2.1实现添加用户操作
2.1.1 修改 UsersMapper 接口
@Insert("insert into users values(default,#{username},#{usersex})")
int insertUsers(Users users);
2.1.2 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class InsertUsersTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("suibian");
users.setUsersex("male");
int flag = usersMapper.insertUsers(users);
sqlSession.commit();
System.out.println(flag);
}
}
2.2实现更新用户操作
2.2.1 修改 UsersMapper 接口
@Update("update users set username = #{username} ,usersex = #{usersex} where userid = #{userid}")
int updateUsers(Users users);
2.2.2 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class UpdateUsersTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("aaa");
users.setUsersex("female");
users.setUserid(24);
int flag = usersMapper.updateUsers(users);
sqlSession.commit();
System.out.println(flag);
}
}
2.3实现删除用户操作
2.3.1 修改 UsersMapper 接口
@Delete("delete from users where userid =#{userid}")
int deleteUsersById(int userid);
2.3.2 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class DeleteUsersByIdTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
int flag = usersMapper.deleteUsersById(24);
System.out.println(flag);
sqlSession.commit();
}
}
3 注解开发中的动态 SQL
在 Mybatis 中的注解开发中,对于动态 SQL 的处理是比较繁琐的,所以如果有动态 SQL 的操作,建议使用映射配置文件文件方式实现。
3.1脚本 SQL
在<script>
标签中通过动态 SQL 的标签完成动态 SQL 的拼接。
3.1.1 修改 UsersMapper 接口
@Select("<script>select * from users where 1 = 1 <if test=\"username != null and username != ''\"> and username = #{username}</if> <if test=\" usersex != null and usersex != ''\"> and usersex = #{usersex}</if></script>")
List<Users> selectUsersByProperty(Users users);
3.1.2 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByPropertyTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("oldlu");
users.setUsersex("male");
List<Users> list = usersMapper.selectUsersByProperty(users);
list.forEach(System.out::println);
}
}
3.2在方法中构建 SQL
在 MyBatis3 的注解中包含了@SelectProvider
、@UpdateProvider
、@DeleteProvider
、 @InsertProvider
,这些注解统称为 SqlProvider,它们分别对应着查询、修改、删除、新增操作。当使用这些注解时将不在注解中直接编写 SQL,而是调用某个类的特定方法来生成 SQL。
3.2.1 修改 UsersMapper 接口
@SelectProvider(type =UsersMapperProvider.class ,method ="selectUsersByPropertySQL" )
List<Users> selectUsersByPropertyProvider(Users users);
class UsersMapperProvider{
/**
* 生成动态sql
*/
public String selectUsersByPropertySQL(Users users){
StringBuffer sb = new StringBuffer("select * from users where 1= 1 ");
if(users.getUsername() != null && users.getUsername() != ""){
sb.append(" and username = #{username}");
}
if(users.getUsersex() != null && users.getUsersex() != ""){
sb.append(" and usersex = #{usersex}");
}
return sb.toString();
}
}
3.2.2 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersByPropertyProviderTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("oldlu");
users.setUsersex("male");
List<Users> list = usersMapper.selectUsersByPropertyProvider(users);
list.forEach(System.out::println);
}
}
4 注解开发中的映射处理
在 Mybatis 中的注解开发中,对于结果集的映射处理也是比较繁琐的,所以如果有结果 集映射操作,建议使用映射配置文件文件方式实现。
4.1映射注解介绍
4.1.1 @Results 注解
代替的标签是<resultMap>
@Results
中的属性介绍:
id
: resultMap 的唯一标识
value
: 通过@Result
注解配置映射关系
4.1.2 @Result 注解
代替了<id>
和<result>
标签
@Result
中的属性介绍:
id
: 是否是主键字段
column
: 数据库的列名
property
: 需要装配的属性名
one
: 需要使用@One
注解(@Result(one = @One()))
many
: 需要使用@Many
注解(@Result(many = @Many()))
4.1.3 @ResultMap 注解
可通过该注复用其他方法上的映射配置
value
: 指定其他@Results
的id
的值。
4.2通过注解实现结果集与对象映射
4.2.1 修改 UsersMapper 接口
@Select("select userid as id ,username as name,usersex as sex from users where userid = #{userid}")
@Results(id = "usersMapper" ,value = {
@Result(id = true,property = "userid",column = "id"),
@Result(property = "username",column = "name"),
@Result(property = "usersex",column = "sex")
})
Users selectUsersByIdMapper(int userid);
@Select("select userid as id ,username as name,usersex as sex from users where userid = #{userid}")
@ResultMap(value = {
"usersMapper"})
Users selectUsersByIdMapper2(int userid);
4.2.2 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class SelectUsersByIdMapperTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
//Users users = usersMapper.selectUsersByIdMapper(1);
Users users = usersMapper.selectUsersByIdMapper2(1);
System.out.println(users);
}
}
5 注解开发中的多表关联查询
在 Mybatis 的注解开发中对于多表查询只支持 N+1 次查询,不支持连接查询。
5.1一对一的关联查询
5.1.1 创建 Roles 实体
package com.bjsxt.pojo;
public class Roles {
private int roleid;
private String rolename;
public int getRoleid() {
return roleid;
}
public void setRoleid(int roleid) {
this.roleid = roleid;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
@Override
public String toString() {
return "Roles{" +
"roleid=" + roleid +
", rolename='" + rolename + '\'' +
'}';
}
}
5.1.2 修改 Users 实体
package com.bjsxt.pojo;
import java.util.List;
public class Users {
private int userid;
private String username;
private String usersex;
private Roles roles;
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsersex() {
return usersex;
}
public void setUsersex(String usersex) {
this.usersex = usersex;
}
@Override
public String toString() {
return "Users{" +
"userid=" + userid +
", username='" + username + '\'' +
", usersex='" + usersex + '\'' +
'}';
}
}
5.1.3 创建 RolesMapper 接口
package com.bjsxt.mapper;
import com.bjsxt.pojo.Roles;
import org.apache.ibatis.annotations.Select;
public interface RolesMapper {
@Select("select * from roles where user_id = #{userid}")
Roles selectRolesByUserId(int userid);
}
5.1.4 修改 UsersMapper 接口
@Select("select * from users where userid = #{userid}")
@Results(id = "usersAndRolesMapper",value = {
@Result(id = true,property = "userid",column = "userid"),
@Result(property = "username",column = "username"),
@Result(property = "usersex",column = "usersex"),
@Result(property = "roles",column = "userid", one = @One(select = "com.bjsxt.mapper.RolesMapper.selectRolesByUserId" ,fetchType = FetchType.LAZY))
})
Users selectUsersAndRolesByUserId(int userid);
5.1.5 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Roles;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class SelectUsersAndRolesByUserIdTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersAndRolesByUserId(1);
System.out.println(users);
Roles roles = users.getRoles();
System.out.println(roles);
}
}
5.2一对多的关联查询
5.2.1 创建 Orders 实体
package com.bjsxt.pojo;
public class Orders {
private int orderid;
private double orderprice;
public int getOrderid() {
return orderid;
}
public void setOrderid(int orderid) {
this.orderid = orderid;
}
public double getOrderprice() {
return orderprice;
}
public void setOrderprice(double orderprice) {
this.orderprice = orderprice;
}
@Override
public String toString() {
return "Orders{" +
"orderid=" + orderid +
", orderprice=" + orderprice +
'}';
}
}
5.2.2 修改 Users 实体
package com.bjsxt.pojo;
import java.util.List;
public class Users {
private int userid;
private String username;
private String usersex;
private Roles roles;
private List<Orders> orders;
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsersex() {
return usersex;
}
public void setUsersex(String usersex) {
this.usersex = usersex;
}
@Override
public String toString() {
return "Users{" +
"userid=" + userid +
", username='" + username + '\'' +
", usersex='" + usersex + '\'' +
'}';
}
}
5.2.3 创建 OrdersMapper 接口
package com.bjsxt.mapper;
import com.bjsxt.pojo.Orders;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface OrdersMapper {
@Select("select * from orders where user_id = #{userid}")
List<Orders> selectOrdersByUserId(int userid);
}
5.2.4 修改 UsersMapper 接口
@Select("select * from users where userid = #{userid}")
@Results(id="usersAndOrdersMapper",value = {
@Result(id = true,property = "userid",column = "userid"),
@Result(property = "username",column = "username"),
@Result(property = "usersex",column = "usersex"),
@Result(property = "orders" ,column = "userid" ,many = @Many(select = "com.bjsxt.mapper.OrdersMapper.selectOrdersByUserId" ,fetchType = FetchType.LAZY))
})
Users selectUsersAndOrdersByUserId(int userid);
5.2.5 创建测试类
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Orders;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class SelectUsersAndOrdersByUserIdTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectUsersAndOrdersByUserId(1);
System.out.println(users);
List<Orders> list = users.getOrders();
list.forEach(System.out::println);
}
}
6 注解开发与映射配置文件的对比
具体在框架中使用注解还是 XML 配置方式,要视框架情况而定。Spring、SpringBoot 中 更推荐注解方式。但是在 MyBatis 中更推荐使用 XML 配置方式。原因如下:
- 使用注解没有实现 Java 代码和 SQL 语句的解耦
- 在 SQL 语句的动态拼接时比较麻烦
- 进行多表的查询时配置 ResultMap 比较麻烦,且不支持连接查询
十一、 Mybatis Generator 工具的使用
MyBatis Generator(MBG)是 MyBatis 官方提供的代码生成工具。MyBatis Generator 工 具可以根据数据库的表结构自动的帮助我们生成模型、接口与映射配置文件,它可以极大地 减少我们对代码的编写,提高开发效率。
1 MyBatis Generator 工具的使用步骤
1.1在 Idea 中打开 MybatisGenerator 项目
1.2修改配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/bjsxt" userId="root"
password="root">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.bjsxt.pojo"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.bjsxt.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.bjsxt.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table schema="" tableName="users"></table>
</context>
</generatorConfiguration>
1.3运行主方法生成 POJO、接口与映射配置文件
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;
public class GeneratorSqlmap {
public void generator() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2 生成代码的结构介绍
2.1模型类
Users 实体类。
2.2Example 类
UsersExample 类封装了针对于 Users 实体类中所用属性的条件定义。它的作用是通过基 于面向对象语法结构来给定操作数据库的条件。
2.3UsersMapper 接口
定义了对数据库 CRUD 操作的抽象方法。
2.4映射配置文件
UsersMapper 接口的映射配置文件。
3 生成代码的使用
3.1查询操作
3.1.1 根据主键查询用户
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
public class SelectUsersByIdTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = usersMapper.selectByPrimaryKey(1);
System.out.println(users);
}
}
3.1.2 多条件查询 and
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.pojo.UsersExample;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* 根据用户姓名与性别查询用户
*/
public class SelectUsersByNameAndSexTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
UsersExample usersExample = new UsersExample();
UsersExample.Criteria criteria = usersExample.createCriteria();
criteria.andUsernameEqualTo("bjsxt");
criteria.andUsersexEqualTo("male");
List<Users> list = usersMapper.selectByExample(usersExample);
list.forEach(System.out::println);
}
}
3.1.3 多条件查询 or
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.pojo.UsersExample;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* 根据用户姓名或者用户性别查询
*/
public class SelectUsersByNameOrSexTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
UsersExample usersExample = new UsersExample();
UsersExample.Criteria criteria = usersExample.createCriteria();
criteria.andUsernameEqualTo("bjsxt");
UsersExample.Criteria criteria1 = usersExample.createCriteria();
criteria1.andUsersexEqualTo("male");
usersExample.or(criteria1);
List<Users> list = usersMapper.selectByExample(usersExample);
list.forEach(System.out::println);
}
}
3.2DML 操作
3.2.1 添加用户
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
/**
* 添加用户
*/
public class InsertUsersTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("kevin");
users.setUsersex("male");
usersMapper.insertSelective(users);
sqlSession.commit();
}
}
3.2.2 更新用户
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
/**
* 更新用户
*/
public class UpdateUsersTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
Users users = new Users();
users.setUsername("zhangsanfeng");
users.setUsersex("male");
users.setUserid(25);
usersMapper.updateByPrimaryKey(users);
sqlSession.commit();
}
}
3.2.3 删除用户
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
/**
* 根据用户ID删除用户
*/
public class DeleteUsersByIdTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
usersMapper.deleteByPrimaryKey(25);
sqlSession.commit();
}
}
十二、 PageHelper 分页插件
PageHelper 是一款非常好用的开源免费的 Mybatis 第三方分页插件。它基于 plugin 的方 式与 Mybatis 整合。通过 PageHelper 所提供的 API 完成对数据的分页查询。
1 PageHelper 使用步骤
1.1添加 jar 包
使用 PageHelper 需要添加两个 jar 包。
pagehelper-5.1.11.jar
jsqlparser-3.1.jar
1.2配置插件
在 Mybatis 的全局配置文件中配置该插件
<!--配置PageHelper分页插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
1.3分页查询 API
PageHelper.startPage(int pageNum,int pageSize);
给定分页参数,该方法需要在执行查询之前调用
pageNum
:起始的页数,从 1 开始计算。
pageSize
:每页显示的条数。
PageInfo
对象
存放分页结果对象
pageInfo.getList()
获取分页查询结果。
pageInfo.getTotal()
获取查询总条数。
pageInfo.getPages()
获取总页数。
pageInfo.getPageNum()
获取当前页。
pageInfo.getSize()
获取每页显示的条数。
2 PageHelper 使用方式
package com.bjsxt.test;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.pojo.UsersExample;
import com.bjsxt.utils.MybatisUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* PageHelper分页测试
*/
public class PageHelperTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
UsersExample usersExample = new UsersExample();
PageHelper.startPage(3,2);
List<Users> list = usersMapper.selectByExample(usersExample);
list.forEach(System.out::println);
PageInfo<Users> pageInfo = new PageInfo<>();
//获取结果集
List<Users> result = pageInfo.getList();
result.forEach(System.out::println);
//获取总条数
System.out.println("总条数:"+pageInfo.getTotal());
//获取总页数
System.out.println("总页数"+pageInfo.getPages());
//获取当前页
System.out.println("当前页"+pageInfo.getPageNum());
//获取每页显示的条数
System.out.println("每页条数"+pageInfo.getSize());
}
}
十三、 Mybatis 与 Servlet 整合
1 搭建环境
1.1创建项目
1.2添加 jar 包
1.3添加配置文件
1.4生成 POJO、接口、映射配置文件
2 OpenSessionInView 的使用
2.1什么是 Open Session In View
Open Session In View 模式:
Open Session In View 是将一个数据库会话对象绑定到当前请求线程中,在请求期间一直 保持数据库会话对象处于 Open 状态,使数据库会话对象在请求的整个期间都可以使用。直 到产生响应后关闭当前的数据库会话对象。
2.2创建 OpenSqlSessionInViewFilter
package com.bjsxt.web.filter;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* 在Filter中打开一个SqlSession
*/
@WebFilter("/*")
public class OpenSqlSessionInViewFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try{
filterChain.doFilter(servletRequest, servletResponse);
sqlSession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
}finally {
MybatisUtils.closeSqlSession();
}
}
@Override
public void destroy() {
}
}
3 完成业务操作
3.1添加用户
3.1.1 修改 index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2021/10/25 0029
Time: 9:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="addUsers.jsp">添加用户</a> <a href="findUsers.jsp">查询用户</a>
</body>
</html>
3.1.2 创建 addUsers.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>添加用户</title>
</head>
<body>
<form action="usersServlet.do" method="post">
<input type="hidden" name="flag" value="addUsers"/>
用户姓名: <input type="text" name="username"/><br/>
用户性别:<input type="text" name="usersex"/><br/>
<input type="submit" value="OK"/>
</form>
</body>
</html>
3.1.3 创建 UsersServlet
package com.bjsxt.web.servlet;
import com.bjsxt.pojo.Users;
import com.bjsxt.service.UsersService;
import com.bjsxt.service.impl.UsersServiceImpl;
import com.github.pagehelper.PageInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/usersServlet.do")
public class UsersServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String flag = req.getParameter("flag");
if("addUsers".equals(flag)){
this.addUsers(req,resp);
}else if("findUsers".equals(flag)){
this.findUsers(req,resp);
}
}
/**
* 处理添加用户请求
*/
private void addUsers(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
Users users = this.createUsers(req);
UsersService usersService = new UsersServiceImpl();
usersService.addUsers(users);
resp.sendRedirect("ok.jsp");
}
/**
* 获取提交数据
*/
private Users createUsers(HttpServletRequest req){
String username = req.getParameter("username");
String usersex = req.getParameter("usersex");
Users users = new Users();
users.setUsername(username);
users.setUsersex(usersex);
return users;
}
}
3.1.4 创建业务层
public interface UsersService {
void addUsers(Users users);
}
package com.bjsxt.service.impl;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.pojo.UsersExample;
import com.bjsxt.service.UsersService;
import com.bjsxt.utils.MybatisUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* 操作用户业务层
*/
public class UsersServiceImpl implements UsersService {
/**
* 添加用户
* @param users
*/
@Override
public void addUsers(Users users) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
usersMapper.insertSelective(users);
}
}
3.1.5 创建成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
操作成功,请返回!
</body>
</html>
3.2查询用户
3.2.1 修改 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="addUsers.jsp">添加用户</a> <a href="findUsers.jsp">查询用户</a>
</body>
</html>
3.2.2 创建 findUsers.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>查询用户</title>
</head>
<body>
<form action="usersServlet.do" method="post">
<input type="hidden" name="flag" value="findUsers"/>
用户姓名: <input type="text" name="username"/><br/>
用户性别:<input type="text" name="usersex"/><br/>
<input type="submit" value="OK"/>
</form>
</body>
</html>
3.2.3 修改 UsersServlet
package com.bjsxt.web.servlet;
import com.bjsxt.pojo.Users;
import com.bjsxt.service.UsersService;
import com.bjsxt.service.impl.UsersServiceImpl;
import com.github.pagehelper.PageInfo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/usersServlet.do")
public class UsersServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String flag = req.getParameter("flag");
if("addUsers".equals(flag)){
this.addUsers(req,resp);
}else if("findUsers".equals(flag)){
this.findUsers(req,resp);
}
}
/**
* 处理添加用户请求
*/
private void addUsers(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
Users users = this.createUsers(req);
UsersService usersService = new UsersServiceImpl();
usersService.addUsers(users);
resp.sendRedirect("ok.jsp");
}
/**
* 获取提交数据
*/
private Users createUsers(HttpServletRequest req){
String username = req.getParameter("username");
String usersex = req.getParameter("usersex");
Users users = new Users();
users.setUsername(username);
users.setUsersex(usersex);
return users;
}
/**
* 查询用户
*/
private void findUsers(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
Users users = this.createUsers(req);
String pageIndex = req.getParameter("pageIndex");
int page = 1;
if(pageIndex != null && pageIndex.length() > 0){
page = Integer.parseInt(pageIndex);
}
UsersService usersService = new UsersServiceImpl();
PageInfo<Users> pageInfo = usersService.findUsers(page,users);
req.setAttribute("pageInfo",pageInfo);
req.setAttribute("users",users);
req.getRequestDispatcher("showUsers.jsp").forward(req,resp);
}
}
3.2.4 修改业务层
PageInfo<Users> findUsers(int page,Users users);
package com.bjsxt.service.impl;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.pojo.UsersExample;
import com.bjsxt.service.UsersService;
import com.bjsxt.utils.MybatisUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* 操作用户业务层
*/
public class UsersServiceImpl implements UsersService {
/**
* 添加用户
* @param users
*/
@Override
public void addUsers(Users users) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
usersMapper.insertSelective(users);
}
/**
* 查询用户
* @param page
* @param users
* @return
*/
@Override
public PageInfo<Users> findUsers(int page, Users users) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
UsersExample usersExample = this.createUsersExample(users);
PageHelper.startPage(page,2);
List<Users> list = usersMapper.selectByExample(usersExample);
PageInfo<Users> pageInfo = new PageInfo<>(list);
return pageInfo;
}
/**
* 生成查询条件
*/
private UsersExample createUsersExample(Users users){
UsersExample usersExample = new UsersExample();
UsersExample.Criteria criteria = usersExample.createCriteria();
if(users.getUsername() != null && users.getUsername().length() > 0){
criteria.andUsernameEqualTo(users.getUsername());
}
if(users.getUsersex() != null && users.getUsersex().length() > 0){
criteria.andUsersexEqualTo(users.getUsersex());
}
return usersExample;
}
}
3.3在显示查询结果页面中实现分页功能
3.3.1 添加 JSTL 标签库的 tld 文件
3.3.2 添加 taglib 指令标签
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3.3.3 创显示查询结果页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>显示查询结果</title>
<script>
function subForm(pageIndex){
document.getElementById("pageIndex").value=pageIndex;
document.forms[0].submit();
}
</script>
</head>
<body>
<form action="usersServlet.do" method="post">
<input type="hidden" name="flag" value="findUsers"/>
<input type="hidden" name="pageIndex" id="pageIndex"/>
<input type="hidden" name="username" value="${users.username}"/>
<input type="hidden" name="usersex" value="${users.usersex}"/>
</form>
<table align="center" border="1" width="40%">
<tr>
<th>用户ID</th>
<th>用户姓名</th>
<th>用户性别</th>
</tr>
<c:forEach items="${pageInfo.list}" var="users">
<tr>
<td>${
users.userid}</td>
<td>${
users.username}</td>
<td>${
users.usersex}</td>
</tr>
</c:forEach>
<tr>
<td colspan="3" align="center">
<c:if test="${pageInfo.pageNum > 1}">
<a href="#" onclick="subForm(${pageInfo.pageNum - 1})">上一页</a>
</c:if>
<c:forEach begin="1" end="${pageInfo.pages}" varStatus="st">
<c:choose>
<c:when test="${pageInfo.pageNum eq st.count}">
<a style="color: red" href="#" onclick="subForm(${st.count})">${
st.count}</a>
</c:when>
<c:otherwise>
<a href="#" onclick="subForm(${st.count})">${
st.count}</a>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${pageInfo.pageNum < pageInfo.pages}">
<a href="#" onclick="subForm(${pageInfo.pageNum + 1})">下一页</a>
</c:if>
</td>
</tr>
</table>
</body>
</html>
下一篇:【Spring】