Mybatis_Mapper动态代理的使用
文章目录
- 一、搭建环境
- 1、创建项目
- 2、添加jar包
- 3、创建实体
- 4、创建Mybatis工具类
- 二、配置Mybatis框架
- 1、添加db.properties文件
- 2、添加log4j.properties文件
- 3、添加全局配置文件
- 4、添加UsersMapper接口
- 5、添加UsersMapper映射配置文件
- 三、实现查询所有用户
- 1、修改映射配置文件
- 2、修改UserMapper接口添加抽象方法
- 3、创建业务层接口
- 4、创建业务层接口实现类
- 5、创建测试类
- 6、运行结果
- 四、实现根据用户ID查询用户
- 1、修改映射配置文件
- 2、修改UsersMapper接口添加抽象方法
- 3、修改业务层接口
- 4、修改业务层接口实现类
- 5、创建测试类
- 五、Mapper 动态代理模式下的多参数处理
- 1、顺序传参法
- 2、@Param注解传参法
- 3、POJO传参法
- 4、Map传参法
- 六、映射配置文件中的特殊字符处理
- 1、使用符号实体
- 2、使用CDATA区
- 七、 Mybatis 的分页查询
- 1、使用 RowBounds
- 1.1、修改映射文件
- 1.2、修改UsersMapper接口
- 1.3、创建测试类
- 2、使用 SQL 语句分页
- 2.1、修改映射配置文件
- 2.2、修改UsersMapper
- 2.3、创建测试类
- 八、Mapper 动态代理模式下的 DML 操作
- 1、实现添加用户业务
- 1.1、修改映射配置文件
- 1.2、修改UsersMapper接口
- 1.3、创建测试类
- 九、主键值回填
- 1、获取自增主键值
- 1.1、开启自动获取自增主键值
- 局部配置:
- 全局配置:
- 1.2、修改UsersMapper接口
- 1.3、创建测试类
- 2、获取非自增主键值
- 2.1、修改映射配置文件
- 2.2、修改UsersMapper接口
- 2.3、创建测试类
一、搭建环境
1、创建项目
2、添加jar包
3、创建实体
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;}@Overridepublic String toString() {return "Users{" +"userid=" + userid +", username='" + username + '\'' +", usersex='" + usersex + '\'' +'}';}
}
4、创建Mybatis工具类
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{//创建SqlSessionFactoryInputStream is = null;try{is = Resources.getResourceAsStream("mybatis-cfg.xml");}catch (IOException e){e.printStackTrace();}sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);}//获取SqlSessionpublic static SqlSession getSqlSession(){SqlSession sqlSession = threadLocal.get();if(sqlSession == null){sqlSession = sqlSessionFactory.openSession();threadLocal.set(sqlSession);}return sqlSession;}//关闭SqlSessionpublic static void closeSqlSession(){SqlSession sqlSession = threadLocal.get();if(sqlSession != null){sqlSession.close();threadLocal.set(null);}}
}
二、配置Mybatis框架
1、添加db.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjsxt
jdbc.username=root
jdbc.password=mysql
2、添加log4j.properties文件
log4j.rootLogger=debug,console,logfile### 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
3、添加全局配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入db.properties属性文件--><properties resource="db.properties"/><!-- 配置别名--><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><!-- 引入Mapper映射配置文件--><mappers><package name="com.bjsxt.mapper"/></mappers>
</configuration>
4、添加UsersMapper接口
public interface UsersMapper {}
5、添加UsersMapper映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjsxt.mapper.UsersMapper"></mapper>
三、实现查询所有用户
1、修改映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjsxt.mapper.UsersMapper"><!-- 查询所有用户--><select id="selectUsersAll" resultType="users">select * from users</select></mapper>
2、修改UserMapper接口添加抽象方法
public interface UsersMapper {List<Users> selectUsersAll();
}
3、创建业务层接口
public interface UsersService {List<Users> findUsersAll();
}
4、创建业务层接口实现类
public class UsersServiceImpl implements UsersService {@Overridepublic List<Users> findUsersAll() {List<Users> list = null;try{SqlSession sqlSession = MybatisUtils.getSqlSession();//getMapper方法的作用是根据给定的接口的Class对象,生成该接口的接口实现类的代理对象UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);list = mapper.selectUsersAll();}catch (Exception e){e.printStackTrace();}finally {MybatisUtils.closeSqlSession();}return list;}
}
5、创建测试类
public class SelectUsersAllTest {public static void main(String[] args) {UsersService usersService = new UsersServiceImpl();List<Users> list = usersService.findUsersAll();//遍历list的两种方式list.forEach(e -> System.out.println(e));list.forEach(System.out::println);}
}
6、运行结果
四、实现根据用户ID查询用户
1、修改映射配置文件
<!-- 根据用户ID查询用户--><select id="selectUsersById" resultType="users">select * from users where userid = #{userid}</select>
2、修改UsersMapper接口添加抽象方法
public interface UsersMapper {List<Users> selectUsersAll();Users selectUsersById(int userid);
}
3、修改业务层接口
public interface UsersService {List<Users> findUsersAll();Users findUsersById(int userid);
}
4、修改业务层接口实现类
@Overridepublic Users findUsersById(int userid) {Users users = null;try{SqlSession sqlSession = MybatisUtils.getSqlSession();UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);users = mapper.selectUsersById(userid);}catch (Exception e){e.printStackTrace();}finally {MybatisUtils.closeSqlSession();}return users;}
5、创建测试类
public class SelectUsersByIdTest {public static void main(String[] args) {UsersService usersService = new UsersServiceImpl();Users users = usersService.findUsersById(1);System.out.println(users);}
}
五、Mapper 动态代理模式下的多参数处理
1、顺序传参法
在映射文件中,SQL 语句中的参数需要使用 arg0,arg1…或者 param1,param2…表示参数的顺序。此方法可读性低,且要求参数的顺序不能出错,在开发中不建议使用。
UsersMapper.java:
List<Users> selectUsersOrderParam(String username,String usersex);
UsersMapper.xml:
<!-- 根据用户姓名与性别查询用户,使用顺序传参法--><select id="selectUsersOrderParam" resultType="users">select * from users where username = #{param1} and usersex =#{param2}</select>
<!-- 根据用户姓名与性别查询用户,使用顺序传参法--><select id="selectUsersOrderParam" resultType="users">select * from users where username = #{arg0} and usersex =#{arg1}</select>
2、@Param注解传参法
在接口方法的参数列表中通过@Param 注解来定义参数名称,在 SQL 语句中通过注解中所定义的参数名称完成参数位置的指定。
此方式在参数不多的情况还是比较直观的,推荐使用。
UsersMapper.xml:
<!-- 根据用户姓名与性别查询用户,使用@Param注解传参法--><select id="selectUsersAnnParam" resultType="users">select * from users where username = #{name} and usersex =#{sex}</select>
UsersMapper.java:
List<Users> selectUsersAnnParam(@Param("name") String username,@Param("sex") String usersex);
3、POJO传参法
在 Mapper 动态代理中也可以使用 POJO 作为传递参数的载体,在 SQL 语句中绑定参数时使用 POJO 的属性名作为参数名即可。此方式推荐使用。
UsersMapper.xml:
<!-- 根据用户姓名与性别查询用户,使用POJO传参法--><select id="selectUsersPOJOParam" resultType="users">select * from users where username = #{username} and usersex =#{usersex}</select>
UsersMapper.java:
List<Users> selectUsersPOJOParam(Users users);
SelectUsersPOJOParamTest.java:
public class SelectUsersPOJOParamTest {public static void main(String[] args) {SqlSession sqlSession = MybatisUtils.getSqlSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);Users users = new Users();users.setUsername("kang");users.setUsersex("male");List<Users> list = usersMapper.selectUsersPOJOParam(users);list.forEach(System.out::println);MybatisUtils.closeSqlSession();}
}
4、Map传参法
在 Mapper 动态代理中也可以使用 Map 作为传递参数的载体,在 SQL 语句中绑定参数时使用 Map 的 Key 作为参数名即可。此方法适合在传递多参数时,如果没有 POJO 能与参数匹配,可以使用该方式传递参数。推荐使用。
MyBatis 传递 map 参数时,如果传递参数中没有对应的 key 值,在执行 sql 语句时默认取的是 null。
UsersMapper.xml:
<!-- 根据用户姓名与性别查询用户,使用Map传参法--><select id="selectUsersMapParam" resultType="users">select * from users where username = #{keyname} and usersex =#{keysex}</select>
UsersMapper.java:
List<Users> selectUsersMapParam(Map<String ,String>map);
SelectUsersMapParamTest.java:
public class SelectUsersMapParamTest {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","kang");map.put("keysex","male");List<Users> list = usersMapper.selectUsersMapParam(map);list.forEach(System.out::println);MybatisUtils.closeSqlSession();}
}
六、映射配置文件中的特殊字符处理
在 Mybatis 的映射配置文件中不可以使用一些特殊字符,如:<,>。
版本较高可用
1、使用符号实体
我们可以使用符号的实体来表示:
<!-- 查询用户ID大于1的用户,特殊字符处理--><select id="selectUsers" resultType="users">select * from users where userid > #{userid}</select>
2、使用CDATA区
CDATA:全称为 Character Data,以"<![CDATA[ "内容" ]]>",CDATA 中的内容不会被解析程序解析。
<!-- 查询用户ID大于1的用户,特殊字符处理--><select id="selectUsers" resultType="users">select * from users where userid <![CDATA[ > ]]> #{userid}</select>
七、 Mybatis 的分页查询
1、使用 RowBounds
RowBounds 是 Mybatis 提供的一个专门处理分页的对象。在 RowBounds 对象中有两个成员变量:
- offset:偏移量,从 0 开始计数
- limit:限制条数
使用 RowBounds 进行分页,非常方便,不需要在 SQL 语句中写 limit,即可完成分页功能。但是由于它是在 SQL 查询出所有结果的基础上截取数据的,所以在数据量大的 SQL中并不适用,它更适合在返回数据结果较少的查询中使用。
1.1、修改映射文件
<!-- 查询所有数据使用RowBounds实现分页处理--><select id="selectUsersRowBounds" resultType="users">select * from users</select>
1.2、修改UsersMapper接口
List<Users> selectUsersRowBounds(RowBounds rowBounds);
1.3、创建测试类
public class SelectUsersRowBoundsTest {public static void main(String[] args) {SqlSession sqlSession = MybatisUtils.getSqlSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);RowBounds rowBounds = new RowBounds(0,2);List<Users> list = usersMapper.selectUsersRowBounds(rowBounds);list.forEach(System.out::println);}
}
2、使用 SQL 语句分页
在分页查询时,如果返回的结果较多,那么需要使用特定的 SQL 语句来实现分页处理。在 MySQL 数据库中我们可以使用 limit 实现分页。
2.1、修改映射配置文件
<!-- 查询所有数据使用limit实现分页处理--><select id="selectUsersLimit" resultType="users">select * from users limit #{offset},#{limit}</select>
2.2、修改UsersMapper
List<Users> selectUsersLimit(@Param("offset") int offset,@Param("limit") int limit);
2.3、创建测试类
public class SelectUsersLimitTest {public static void main(String[] args) {SqlSession sqlSession = MybatisUtils.getSqlSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);List<Users> list = usersMapper.selectUsersLimit(0,2);list.forEach(System.out::println);MybatisUtils.closeSqlSession();}
}
八、Mapper 动态代理模式下的 DML 操作
1、实现添加用户业务
1.1、修改映射配置文件
<!-- 添加用户--><insert id="insertUsers">insert into users values (default ,#{username},#{usersex})</insert>
1.2、修改UsersMapper接口
int insertUsers(Users users);
1.3、创建测试类
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("kkkkkyyyyyyyyyy");users.setUsersex("male");int flag = usersMapper.insertUsers(users);System.out.println(flag);sqlSession.commit();MybatisUtils.closeSqlSession();}
}
九、主键值回填
在数据库中插入数据时,有时我们是需要获取新数据的主键值。在 Mybatis 中支持主键值回填,可以让我们更够更方便的获取新添加数据的主键值。
Mybatis 中支持两种方法获取主键:
获取自增主键的值。如:MySQL、SqlServer
获取非自增主键的值。如 Oracle
1、获取自增主键值
1.1、开启自动获取自增主键值
有两种方式:
- 局部配置
- 全局配置
局部配置:
映射配置文件:
<!-- 添加用户获取主键值(自增)--><insert id="insertUsersGetKey" useGeneratedKeys="true" keyProperty="userid">insert into users values (default ,#{username},#{usersex})</insert>
全局配置:
全局配置文件:
<settings>
<setting name="useGeneratedKeys" value="true"/>
</settings>
映射配置文件:
<!--添加用户获取主键值[自增]-->
<insert id="insertUsersGetKey" keyProperty="userid">
insert into users values(default ,#{username},#{usersex})
</insert>
1.2、修改UsersMapper接口
void insertUsersGetKey(Users users);
1.3、创建测试类
public class InsertUsersGetKeyTest {public static void main(String[] args) {SqlSession sqlSession = MybatisUtils.getSqlSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);Users users = new Users();users.setUsername("aaaaaa");users.setUsersex("male");usersMapper.insertUsersGetKey(users);sqlSession.commit();System.out.println(users.getUserid());MybatisUtils.closeSqlSession();}
}
2、获取非自增主键值
2.1、修改映射配置文件
在Mysql数据库中获取插入数据的主键的值有两种:select LAST_INSERT_ID() ,
SELECT @@Identity。
SELECT @@Identity是select LAST_INSERT_ID() 的同义词,两者作用是相同的
<!-- 添加用户获取主键值【非自增】 oracle[order:Before] mysql[order:After]--><insert id="insertUsersGetKey2"><selectKey order="AFTER" keyProperty="userid" resultType="int">select LAST_INSERT_ID()</selectKey>insert into users values(default ,#{username},#{usersex})</insert>
</mapper>
2.2、修改UsersMapper接口
void insertUsersGetKey2(Users users);
2.3、创建测试类
public class InsertUsersGetKey2Test {public static void main(String[] args) {SqlSession sqlSession = MybatisUtils.getSqlSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);Users users = new Users();users.setUsername("kangkang");users.setUsersex("male");usersMapper.insertUsersGetKey2(users);sqlSession.commit();System.out.println(users.getUserid());MybatisUtils.closeSqlSession();}
}
Mybatis_Mapper动态代理的使用相关推荐
- 【spring】动态代理
代理 动态代理 特点:字节码随用随创建,随用随加载 作用:不修改源码的基础上对方法增强 分类:基于接口的动态代理.基于子类的动态代理 基于接口的动态代理: 涉及的类:Proxy 提供者:JDK ...
- (转)面试必备技能:JDK动态代理给Spring事务埋下的坑!
一.场景分析 最近做项目遇到了一个很奇怪的问题,大致的业务场景是这样的:我们首先设定两个事务,事务parent和事务child,在Controller里边同时调用这两个方法,示例代码如下: 1.场景A ...
- Java动态代理和静态代理区别
静态代理 package staticproxy;/*** 接口* @author newtouch**/ public interface IHello {public void sayHello( ...
- java动态代理【一】
java动态代理的定义:为其他目标类的方法增加切面的逻辑,即在执行目标类方法的时候,先去执行一段如校验检测的逻辑代码.java通俗一点就是生成一个继承目标类的子类,并在每个调用方法都添加一段逻辑. 应 ...
- 支撑Java框架的基础技术:泛型,反射,动态代理,cglib
以Spring为例要想看明白他的源码需要彻底理解Java的一些基础技术泛型,反射同时对于一些高级技术例如动态代理,cglib和字节码技术也需要掌握,下面就按章节来一一说清楚这些技术的核心部分,最后手写 ...
- 支撑Spring的基础技术:泛型,反射,动态代理,cglib等
1.静态代码块和非静态代码块以及构造函数 出自尚学堂视频:<JVM核心机制 类加载全过程 JVM内存分析 反射机制核心原理 常量池理解> public class Parent {stat ...
- 【spring】初识aop(面向切面编程) 使用jdk动态代理
BankServiceIImple.java 代码实现: package com.zzxtit.aop;import java.math.BigDecimal;public interface Ban ...
- java静态代理与动态代理
2019独角兽企业重金招聘Python工程师标准>>> 代理模式是java常见的设计模式.其目的是为其他对象提供一个代理以控制对某个真实对象的访问.通过代理类这一中间层,有效控制对真 ...
- Java动态代理机制
在Java的动态代理机制中,有两个重要的类.一个是InvocationHandler,另一个是Proxy. InvocationHandler:每一个动态代理类都必须要实现InvocationHand ...
最新文章
- 原生js ajax请求 post,原生js实现ajax 发送post请求
- ​JGG | TaxonKit:一款实用又高效的NCBI分类学数据工具包
- java 面试题汇总
- MFC中的DC,CDC和HDC
- java 查找list中指定字符串出现的次数
- python scrapy框架 简书_python爬虫框架——Scrapy架构原理介绍
- web下拉列表代码_文章列表总结(一)
- Winform文件下载之WebClient
- 动态创建form传参
- ios 配置java环境变量_Ios 入门 ----基本的控件
- java线程池服务ExecutorService
- docker安装redis【网易镜像方式】
- spyder4升级到spyder5出现缺少依赖库spyder_kernels问题解决
- Device Owner模式
- 中国最美的一千个汉字 : 千字文5
- 正确的临摹方法,小白零基础临摹教程
- git合并分支Pulling is not possible because you have unmerged files.
- 蓝牙耳机连接电脑无法调节音量
- go gorm获取数据库报错:goexit: BYTE $0x90 // NOP
- PIC反汇编 MPLAB HEX
热门文章
- 如何面试Java中级开发(16k)试题讲解和Java学习
- js实现数字从1动态递增到10
- 软件工程——成本效益分析
- 使用w3c解析xml文档
- 陈飞龙 java,二、简单几步下载安装JMeter
- python过京东app图形验证勾股定理_Python爬虫模拟登录京东获取个人信息
- firefox常见问题解答
- 中科红旗卖身内幕:收购方放言不惜代价拿下
- Go实战--golang中使用gRPC和Protobuf实现高性能api(golang/protobuf、google.golang.org/grpc)
- C0216:输入矩形的长和宽,输出周长和面积