Mybatis3详解(五)----通过Mapper接口(动态代理)加载映射文件(推荐)
1、本章前言
前面学习了基于原生接口的xml版本创建Mybatis实例( 链接 ),就是通过sqlSession对象调用其内部定义好的相对应的方法,包括增删改查方法,如selectOne、selectList、insert等等,但这种方式在实际中很少使用,不推荐。所以下面我们来学习一种在我们平时开发中最常用也是最实用的开发方式——通过Mapper接口(动态代理)加载映射文件。Mapper接口动态代理的方式需要程序员手动编写Mapper接口(相当于Dao接口),由Mybatis框架将根据接口定义创建接口的动态代理对象,代理对象的方法体实现Mapper接口中定义的方法。
下面就来学习这种方法创建一个Mybatis的实例。
2、创建数据库
创建数据库(mybatis)和表(t_user),SQL脚本如下:
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`age` int(11) NULL DEFAULT NULL,
`sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, '奥利给', 18, '男', '上海');
INSERT INTO `t_user` VALUES (2, '蔡徐坤', 18, '男', '北京');
INSERT INTO `t_user` VALUES (3, '黄飞鸿', 42, '男', '大清');
INSERT INTO `t_user` VALUES (4, '十三姨', 18, '女', '大清');
INSERT INTO `t_user` VALUES (5, '梁宽', 42, '男', '大清');
3、创建Maven项目
在Eclipse或IDEA中创建一个Maven项目。
然后导入pom依赖,如下:
<dependencies>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
4、编写User实体类
创建一个User实体类,这里省略了getter、setter和toString方法,需自己加上。
/**
* 用户实体类
*/
public class User {
private int userId;
private String userName;
private int userAge;
private String userSex;
private String userAddress;
//getter、setter、toString方法省略......
}
5、创建Mybatis全局配置文件
在resources目录中,创建Mybatis的全局配置文件mybatis-config.xml。代码如下:
注意:这里面配置了别名,扫描所有实体包,给实体类起个别名,别名就是小写字母的类名。
<?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>
<!--配置别名-->
<typeAliases>
<!-- 对包进行扫描,可以批量进行别名设置,设置别名的规则是:获取类名称,将其第一个字母变为小写 -->
<package name="com.thr.entity"/>
</typeAliases>
<!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境 -->
<environments default="development">
<!-- environment表示配置Mybatis的一个具体的环境 -->
<!-- id属性必须和上面的default一致 -->
<environment id="development">
<!--配置Mybatis的内置的事务管理器-->
<transactionManager type="JDBC"/>
<!--dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象源 -->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
6、编写Mapper接口
Mapper接口代码代码如下(命名不一定是XxxMapper,也可以是XxxDao等等):
/**
* UserMapper接口
*/
public interface UserMapper {
//查询所有用户
List<User> selectAllUser();
//根据id查询用户
User selectUserById(Integer id);
//根据用户名模糊查询用户列表
List<User> selectUserByName(String userName);
//添加用户
Integer insertUser(User user);
//修改用户信息
Integer updateUser(User user);
//删除用户
Integer deleteUser(Integer id);
}
7、编写SQL映射文件(非常重要)
在resources里创建目录:com/thr/mapper,然后在里面创建映射配置文件UserMapper.xml。注意:目录在创建时是斜杠(/)而不是点(.),如果用点(.)的话表示创建了一个名字为com.thr.mapper的文件,而不是com->thr->mapper的目录,到时候在加载映射文件的时候报错。
编写映射文件的注意事项如下(非常重要!非常重要!非常重要!):
- XML文件名的命名必须和Mapper接口名称相同,例如UserMapper.xml。
- SQL映射文件中命名空间namespace必须对应Mapper接口的全限定类名。
- 增删改查元素中的id与Mapper接口中的方法必须对应。
- parameterType的类型必须和Mapper接口方法的输入参数类型相同(有时可以省略)。
- resultType的类型必须和Mapper接口方法的输出参数类型相同。
映射文件的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属性:表示命名空间,用来设定当前Mapper配置文件的唯一标识,将来在Java程序中通过namespace属性的值来定位到这个配置文件 -->
<!-- namespace属性值设置的方式:名字可以随便取,但是推荐以相对应的Mapper接口的全类名,例如com.thr.mapper.UserMapper -->
<mapper namespace="com.thr.mapper.UserMapper">
<!-- 配置查询结果的列名和实体类的属性名的对应关系 -->
<!--id:唯一标识,type:需要映射的java类型-->
<resultMap id="userMap" type="com.thr.entity.User">
<!-- 与主键字段的对应,property对应实体属性,column对应表字段 -->
<id property="userId" column="id"/>
<!-- 与非主键字段的对应,property对应实体属性,column对应表字段 -->
<result property="userName" column="username"/>
<result property="userAge" column="age"/>
<result property="userSex" column="sex"/>
<result property="userAddress" column="address"/>
</resultMap>
<!-- 查询所有用户 -->
<select id="selectAllUser" resultMap="userMap">
select * from t_user;
</select>
<!-- 通过Id查询一个用户 -->
<select id="selectUserById" parameterType="int" resultMap="userMap">
select * from t_user where id = #{id};
</select>
<!-- 模糊查询,根据username字段查询用户-->
<select id="selectUserByName" parameterType="int" resultMap="userMap">
select * from t_user where username like '%${value}%';
</select>
<!-- 添加用户-->
<insert id="insertUser" parameterType="com.thr.entity.User">
insert into t_user(username, age, sex, address)
values (#{userName}, #{userAge}, #{userSex}, #{userAddress});
</insert>
<!-- 根据Id更新用户 -->
<update id="updateUser" parameterType="com.thr.entity.User">
update t_user set username = #{userName},age = #{userAge},sex = #{userSex},address = #{userAddress} where id = #{userId}
</update>
<!-- 根据Id删除用户 -->
<delete id="deleteUser" parameterType="int">
delete from t_user where id = #{id}
</delete>
</mapper>
8、加载映射文件
将上面创建的UserMapper.xml文件添加至全局配置文件mybatis-config.xml下。
注意:通过注册Mapper接口或者包扫描的方式创建mapper.xml,它的位置必须和Mapper接口在相同的包或者相同目录下才能获取到对应的xml文件。
<mappers>
<!-- 注册UserMapper.xml文件 -->
<!-- 这种方式Mapper接口和mapper.xml文件可以不在一个包下 -->
<!--<mapper resource="com/thr/mapper/UserMapper.xml"/>-->
<!-- 注册Mapper接口 -->
<!-- 通过注册Mapper接口方式: Mapper接口和mapper.xml必须在同一个包下,并且二者名字也必须相同-->
<!-- <mapper class="com.thr.mapper.UserMapper"/> -->
<!-- 扫描包下的所有mapper接口并进行注册,规则必须是同包同名 -->
<package name="com.thr.mapper"/>
</mappers>
9、导入日志文件
导入日志文件,在resources目录中创建log4j.xml文件(这种方式打印的数据更加清晰),并且导入如下配置(如果log报错则以管理员的方式启动Eclipse或IDEA)。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="info" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
10、编写测试文件
最后创建一个MybatisTest的测试类,其源代码如下所示:
/**
* Mybatis的测试
*/
public class MybatisTest {
//定义 SqlSession
private SqlSession sqlSession = null;
//定义 UserMapper对象
private UserMapper mapper = null;
@Before//在测试方法执行之前执行
public void getSqlSession(){
//1、加载 mybatis 全局配置文件
InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3、根据 sqlSessionFactory 产生 session
sqlSession = sqlSessionFactory.openSession();
//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成UserMapper的代理实现类
mapper = sqlSession.getMapper(UserMapper.class);
}
@After//在测试方法执行完成之后执行,这里也有提交事务和关闭资源
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
}
//查询所有用户数据
@Test
public void testSelectAllUser(){
List<User> listUser = mapper.selectAllUser();
for (User user : listUser) {
System.out.println(user);
}
}
//根据Id查询一个用户数据
@Test
public void testSelectUserById(){
User user = mapper.selectUserById(1);
System.out.println(user);
}
//模糊查询:根据 user 表的username字段
@Test
public void testSelectUserByName(){
List<User> userList = mapper.selectUserByName("三");
for(User user : userList){
System.out.println(user);
}
}
//添加一个用户数据
@Test
public void testInsertUser(){
User user = new User();
user.setUserName("法外狂徒张三");
user.setUserAge(42);
user.setUserSex("男");
user.setUserAddress("中国监狱");
Integer i = mapper.insertUser(user);
System.out.println(i);
System.out.println( (i>0)? "添加成功!":"添加失败!");
}
//根据Id修改用户数据
@Test
public void testUpdateUser(){
//如果设置的 id不存在,那么数据库没有数据更改
User user = new User();
user.setUserId(3);
user.setUserName("梁宽");
user.setUserAge(42);
user.setUserSex("男");
user.setUserAddress("中国北京");
Integer i = mapper.updateUser(user);
System.out.println( (i>0)? "修改成功!":"修改失败!");
}
//根据Id删除用户数据
@Test
public void testDeleteUser(){
Integer i = mapper.deleteUser(3);
System.out.println( (i>0)? "删除成功!":"删除失败!");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!