MyBatis总结三:使用动态代理实现dao接口
由于我们上一篇实现MyBatis的增删改查的接口实现类的方法都是通过sqlsession调用方法,参数也都类似,所以我们使用动态代理的方式来完善这一点
-
编写数据管理的接口 XxxMapper.java
-
编写接口对应的配置文件 XxxxMapper.xml
-
namespace必须 和 dao接口的全路径保持一致 (即物理路径的文件夹名称相同)
-
statement的id必须 和 dao接口的方法名保持一致
-
statement的resultType类型 必须 和方法返回值类型保持一致
-
-
通过 sqlSession.getMapper(类的字节码对象) 获取代理之后的Mapper实现类对象
首先我们在之前项目的基础上编写Mapper接口(代替Dao接口):
package com.zy.mapper; import com.zy.domain.User; import java.util.List; public interface UserMapper { /** * 根据id查询用户信息 */ public User getUserById(int id); /** * 查询所有用户信息 */ public List<User> getUserList(); /** * 添加用户信息 */ public void addUser(User user); /** * 修改用户信息 */ public void updateUser(User user); /** * 根据id删除用户信息 */ public void deleteUser(int id); }
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> <!--加载外部属性--> <properties resource="jdbc.properties"/> <!--起别名--> <typeAliases> <typeAlias type="com.zy.domain.User" alias="User"></typeAlias> </typeAliases> <!--运行环境可以配置多个, default指定默认使用哪个--> <environments default="development"> <!--配置环境, id是这个环境的唯一标识--> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!--3 指定所有的mapper文件--> <mappers> <!--如果只需要管理一个mapper 可以直接写如下方式 并且其物理路径不需要与其xml文件路径相同--> <!--<mapper resource="UserMapper.xml"></mapper>--> <!--我们如果需要统一管理所有的mapper xml 用这种方式 但是这种方式需要文件夹路径和其xml文件的name路径一致--> <package name="com.zy.mapper" /> </mappers> </configuration>
然后修改UserMapper.xml文件的物理路径以及内容:
由于我们mybatis-config里面映射器中使用的是package管理方式 所以mapper xml文件的物理路径需要跟其xml文件内的namespace值一致
所以把UserMapper.xml的位置改成如下:
这里需要注意一点 这个com.zy.mapper不是文件夹,是package,如果创建成普通文件夹的话,运行的时候会报 invalid bound statement (not found) 的错误
<?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"> <!-- 定义所有用到的sql语句 和 映射关系 namespace : 当前这个配置文件的唯一标识, 自定义, 但是不能和其他配置文件namespace重复 --> <mapper namespace="com.zy.mapper.UserMapper"> <!-- 定义一条sql语句, 其实就是一个 statement select 代表是查询语句, 与其类似的还有 insert, update, delete等 id : 这条sql语句的唯一标识,自定义,但是不能和其他sql语句重复 parameterType: sql语句需要的参数类型, 需要写 类的全路径 resultType: sql语句返回的结果类型 --> <select id="getUserById" parameterType="int" resultType="com.zy.domain.User"> <!--这里写具体的sql语句, #{}是占位符, 编译时会被替换成?, 然后注入真实参数--> select * from user where id=#{id} </select> <!--查询所有用户信息--> <select id="getUserList" resultType="com.zy.domain.User"> select * from user </select> <!--添加用户信息--> <insert id="addUser" parameterType="com.zy.domain.User"> insert into user (id,name,age) values (null,#{name},#{age}) </insert> <!--修改用户信息--> <update id="updateUser" parameterType="com.zy.domain.User"> update user set name=#{name}, age=#{age} where id=#{id} </update> <!--删除用户信息--> <delete id="deleteUser" parameterType="int"> delete from user where id=#{id} </delete> </mapper>
然后进行单元测试(我们调用的时候 可以直接用接口调用方法执行sql语句了):
package com.zy.mapper; import com.zy.dao.UserDaoTest; import com.zy.domain.User; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import java.io.InputStream; import java.util.List; import static org.junit.Assert.*; public class UserMapperTest { UserMapper mapper; @Before public void setUp() throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = UserDaoTest.class.getClassLoader().getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); //使用反射 mapper = sqlSession.getMapper(UserMapper.class); } @Test public void getUserById() throws Exception { User user = mapper.getUserById(1); System.out.println(user); } @Test public void getUserList() throws Exception { List<User> list = mapper.getUserList(); for (User user : list) { System.out.println(user); } } @Test public void addUser() throws Exception { User user = new User(); user.setName("郭富城"); user.setAge(18); mapper.addUser(user); } @Test public void updateUser() throws Exception { //先查 User user = mapper.getUserById(2); //后改 user.setName("黎明"); user.setAge(17); mapper.updateUser(user); } @Test public void deleteUser() throws Exception { mapper.deleteUser(2); } }