目标对象不可访问,需要通过动态代理对象增强功能访问
动态代理存在的意义
在三层架构中,业务逻辑层要通过接口访问数据访问层的功能,动态代理可以实现
我想要调用的是对应接口的方法,但又不想解析xml文件,调用方法直接用就完了我要的是功能,而不是sql语句所以动态代理可以解决这个问题
MyBaits中动态代理的实现规范
- 1)
UsersMapper.xml文件与UsersMapper.java的接口必须同一个目录下 - 2)
UsersMapper.xml文件与UsersMapper.java的接口的文件必须一致,后缀不管(必须都叫同一个名称) - 3)
UsersMapper.xml文件中标签的id值与UsersMapper.java的接口中方法的名称完全一致 - 4)
UsersMapper.xml文件中标签的parameterType的属性值与UsersMapper.java的接口中方法的参数类型完全一致 - 5)
UsersMapper.xml文件中resultType值与UsersMapper.java的接口中方法的返回值类型完全一致 - 6)
UsersMapper.xml文件中namespace的属性必须是接口的完全限定名称(com.chentianyu.mapper.UsersMapper) - 7)在
SqlMapperConfig.xml(核心配置文件)文件中注册mapper文件时,使用class=接口的完全限定名称(com.chentianyu.mapper.UsersMapper) - 这么多一致就是把这个接口与xml标签绑在一起,全部做成一样的,调接口就是调用标签
创建项目
New Project->Maven->勾选Create from archetype->maven-archetype-quickstart->(projectName,路径,GroupId(包名)) -Next-> 默认(Finish)
动态代理访问的步骤
- 创建Users
- 新建maven工程,刷新可视化(
IDEAIJ中最右Maven旁的Database) - 修改目录
- 修改
pom.xml文件- 添加依赖
- 添加
jdbc.properties文件到resources目录下 - 添加
核心配置文件 - 添加实体类
- 添加
mapper文件夹- 新建
xxxmapper接口
- 新建
- 在
mapper文件夹下- 新建
xxxmaper.xml完成增删改查功能
- 新建
- 添加测试类,测试功能
创建Users
USE ssm;-- ------ Table structure for `users`-- -----DROP TABLE IF EXISTS `users`;CREATE TABLE `users`(`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,`username` VARCHAR(255) COMMENT '用户名称',`birthday` DATE DEFAULT NULL COMMENT '生日',`sex` CHAR(2) DEFAULT NULL COMMENT '性别',`address` VARCHAR(256) DEFAULT NULL COMMENT '地址')ENGINE=INNODB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;-- ------------- Records of User-- -----------INSERT INTO `users` VALUES(1,"王五",'2000-09-10','1','安徽');#自增,但是可以直接给值INSERT INTO `users` VALUES(2,"李四",'2000-05-19','1','上海市');INSERT INTO `users` VALUES(3,"张三",'2000-07-03','1','北京');SELECT * FROM `users`;
IDEA中DataBase(最右边Maven旁边)'+'号,Data Source选择MySQL,选择用户名,密码和要连接的数据库名称-> Test Connection(测试)->OK
修改目录+pom.xml文件
- resources
项目根目录->src->main(new Directory(resources)) -> Mark Directory As(Resources Root)项目根目录->src->test(new Directory(resources)) -> Mark Directory As(Test Resources Root)- 删除自带的
AppTest.java和App.java
- 创建
pojo包,mapper包- 目录结构
项目名 |_.idea |_src |__main |___java |____com |_____chentianyu |______mapper |______pojo |__resources |___jdbc.properties |___mybatis.xml(核心配置文件) |_test |__java |___com |____chentianyu |__resources
- 目录结构
pom.xml改造
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chentianyu</groupId>
<artifactId>JDKDL_MyBatis_Learn_One</artifactId>
<version>1.0-SNAPSHOT</version>
<name>JDKDL_MyBatis_Learn_One</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--添加mybatis的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!--添加mysql的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
<build>
<!--指定资源文件的位置-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
</project>
jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm
jdbc.username=root
jdbc.password=自己的密码
mybatis.xml(核心配置文件)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybaits.org//Configuration 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--读取jdbc.properties属性-->
<properties resource="jdbc.properties"></properties>
<!--设置日志输出-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--注册实体类的别名-->
<typeAliases>
<package name="com.chentianyu.pojo"/>
</typeAliases>
<!--配置环境变量-->
<environments default="one">
<environment id="one">
<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.xml文件-->
<mappers></mappers>
</configuration>
实体类构建
package com.chentianyu.pojo;
import java.util.Date;
public class Users {
private Integer id;
private String userName;//列名无所谓,类中成员变量必须大驼峰写法
private Date birthday;
private String sex;
private String address;
public Users() {
}
public Users(Integer id, String userName, Date birthday, String sex, String address) {
this.id = id;
this.userName = userName;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}
public Users(String userName, Date birthday, String sex, String address) {
this.userName = userName;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
参数构造可以使用**alt+ins/alt+fn+ins**来构建构造方法和**getter and setter**
新建xxxmapper接口
UsersMapper.java
package com.chentianyu.mapper;
import com.chentianyu.pojo.Users;
import java.util.List;
/**
* 数据访问层的接口,规定了数据库中可进行的各种操作
*/
public interface UsersMapper {
//查询用户的全部信息
List<Users> getAll();
}
UsersMapper.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.chentianyu.mapper.UsersMapper">
<!--
//查询全部用户信息
List<Users> getAll()
-->
<select id="getAll" resultType="users">
select * from users
</select>
</mapper>
记得要在核心配置文件中注册Mappper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybaits.org//Configuration 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
...
<!--注册mapper.xml文件-->
<mappers>
<mapper class="com.chentianyu.mapper.UsersMapper"></mapper>
</mappers>
</configuration>
测试
package com.chentianyu.test;
import com.chentianyu.mapper.UsersMapper;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
/**
*
*/
public class MyTest {
SqlSession sqlSession;
@Before
public void test01() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
sqlSession = factory.openSession();
}
@Test
public void test02(){
//重点: 取出代理的对象,完成接口中方法的调用,实则是调用xml文件中相同标签的功能
UsersMapper uMapper = sqlSession.getMapper(UsersMapper.class);
System.out.println(uMapper.getClass());
//sqlSession.selectList("");
}
@After
public void test03(){
sqlSession.close();
}
}
你会看到
class jdk.proxy2.$Proxy9
这就是jdk动态代理的类型
所以
package com.chentianyu.test;import com.chentianyu.mapper.UsersMapper;import com.chentianyu.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.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;import java.util.List;/** * */public class MyTest { SqlSession sqlSession; @Before public void test01() throws IOException { InputStream in = Resources.getResourceAsStream("mybatis.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(); } @Test public void test02(){ //重点: 取出代理的对象,完成接口中方法的调用,实则是调用xml文件中相同标签的功能 UsersMapper uMapper = sqlSession.getMapper(UsersMapper.class); System.out.println(uMapper.getClass()); //List<Users> list = sqlSession.selectList(""); //就是在调试接口的方法,mybatis框架已经为我们把功能代理出来了 List<Users> list = uMapper.getAll(); list.forEach(users -> System.out.println(users)); } @After public void test03(){ sqlSession.close(); }}
用户更新
package com.chentianyu.mapper;import com.chentianyu.pojo.Users;import java.util.List;/** * 数据访问层的接口,规定了数据库中可进行的各种操作 */public interface UsersMapper { //查询全部用户信息 List<Users> getAll(); //根据用户主键查用户 //根据用户名模糊查询用户 //用户更新 int update(Users users); //添加用户 //根据主键删除用户}
UsersMapper.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.chentianyu.mapper.UsersMapper"> <!-- //查询全部用户信息 List<Users> getAll() --> <select id="getAll" resultType="users"> select * from users </select> <!-- //用户更新 int update(Users users); private Integer id; private String userName; private Date birthday; private String sex; private String address; --> <update id="update" parameterType="users"> update users set username=#{userName},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update></mapper>
测试类
public class MyTest {
SqlSession sqlSession;
UsersMapper uMapper;
@Before
public void test01() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
sqlSession = factory.openSession();
uMapper = sqlSession.getMapper(UsersMapper.class);
}
@Test
public void test02(){
//重点: 取出代理的对象,完成接口中方法的调用,实则是调用xml文件中相同标签的功能
System.out.println(uMapper.getClass());
//List<Users> list = sqlSession.selectList("");
//就是在调试接口的方法,mybatis框架已经为我们把功能代理出来了
List<Users> list = uMapper.getAll();
list.forEach(users -> System.out.println(users));
}
@After
public void test03(){
sqlSession.close();
}
@Test
public void testUpdate01(){
Users users = new Users(2,"haha",new Date(),"2","北京");
int num = uMapper.update(users);
System.out.println(num);
//切记: 手工提交
sqlSession.commit();
}
}
可以是可以,就是我们不能一直这么去获取**你当前的时间**,得用**格式刷**
public class MyTest {
SqlSession sqlSession;
//动态代理对象
UsersMapper uMapper;
//日期的格式化刷子
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
@Before
public void test01() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
sqlSession = factory.openSession();
uMapper = sqlSession.getMapper(UsersMapper.class);
}
@Test
public void test02(){
//重点: 取出代理的对象,完成接口中方法的调用,实则是调用xml文件中相同标签的功能
System.out.println(uMapper.getClass());
//List<Users> list = sqlSession.selectList("");
//就是在调试接口的方法,mybatis框架已经为我们把功能代理出来了
List<Users> list = uMapper.getAll();
list.forEach(users -> System.out.println(users));
}
@After
public void test03(){
sqlSession.close();
}
@Test
public void testUpdate01() throws ParseException {
Users users = new Users(2,"haha6",sf.parse("2000-01-02"),"2","北京");
int num = uMapper.update(users);
System.out.println(num);
//切记: 手工提交
sqlSession.commit();
}
}
Ctrl+p(查看方法返回值)
根据主键id查询用户
UsersMapper.java
public interface UsersMapper { //查询全部用户信息 List<Users> getAll(); //根据用户主键查用户 Users getById(Integer id); //根据用户名模糊查询用户 //用户更新 int update(Users users); //添加用户 //根据主键删除用户}
UsersMapper.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.chentianyu.mapper.UsersMapper">.... <!-- //根据用户主键查用户 Users getById(); --> <select id="getById" resultType="users" parameterType="int"> select * from users where id=#{id} </select></mapper>
测试类
public class MyTest { SqlSession sqlSession; //动态代理对象 UsersMapper uMapper; //日期的格式化刷子 SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); @Before public void test01() throws IOException { InputStream in = Resources.getResourceAsStream("mybatis.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); sqlSession = factory.openSession(); uMapper = sqlSession.getMapper(UsersMapper.class); } ... @Test public void testSelectById(){ Users users = uMapper.getById(3); System.out.println(users); }}
根据用户名模糊查询
public interface UsersMapper {
....
//根据用户名模糊查询用户
List<Users> getLikeByName(String name);
...
}
<?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.chentianyu.mapper.UsersMapper">
....
<!--
//根据用户名模糊查询用户
List<Users> getLikeByName(String name);
-->
<select id="getLikeByName" resultType="users" parameterType="string">
select * from users where username like "%${name}%"
</select>
</mapper>
测试
@Test
public void testGetByName(){
List<Users> list = uMapper.getLikeByName("三");
list.forEach(users -> System.out.println(users));
}
增加用户
/** * 数据访问层的接口,规定了数据库中可进行的各种操作 */public interface UsersMapper { .... //添加用户 int insertUsers(Users users); //根据主键删除用户}
<?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.chentianyu.mapper.UsersMapper">
....
<!--
//添加用户
Users insertUsers(Users users);
private String userName;
private Date birthday;
private String sex;
private String address;
-->
<insert id="insertUsers" parameterType="users">
insert into users(username,birthday,sex,address) values(#{userName},#{birthday},#{sex},#{address})
</insert>
</mapper>
测试
@Test
public void testInsertUsers() throws ParseException {
int num = uMapper.insertUsers(new Users("李明", sf.parse("2001-02-05"), "1", "大兴"));
System.out.println(num);
sqlSession.commit();
}
根据主键删除用户
public interface UsersMapper {
...
//根据主键删除用户
int deleteUsers(Integer id);
}
<?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.chentianyu.mapper.UsersMapper">
....
<!--
//根据主键删除用户
int deleteUsers(Integer id);
-->
<delete id="deleteUsers" parameterType="int">
delete from users where id=#{id}
</delete>
</mapper>
测试
@Test
public void testDeleteUsers(){
int num = uMapper.deleteUsers(29);
System.out.println(num);
sqlSession.commit();
}
