原始DAO的开发方式
存在问题
- Dao实现类中存在重复代码(通过SqlSessionFactory创建创建SqlSession,调用SqlSession操作数据库)
- 使用SqlSession操作数据库的方法,都需要传递statement的id,存在硬编码,不利于维护
- 使用SqlSession操作数据库的方法,传递的参数可以是任何类型,在编译阶段不会报错,这种方式不利于程序开发
动态代理
概念
- 动态代理就是在程序运行期间为被代理对象生成代理对象
- JDK动态代理,只能代理的是接口,要想代理类可以使用cglib
实现方式
- 必须要实现一个接口InvocationHandler
- 还需要调用Proxy中的newProxyInstance()方法创建代理类
实现步骤
- 创建被代理的接口(目标对象)
- 创建实现InvocationHandler接口的实现类,重写invoke方法实现我们想要的代理逻辑
- 创建代理对象(通过Proxy的newProxyInstance()方法实现)
Mapper动态代理
实现原理
- Mapper动态代理的开发方法,只需要编写Mapper接口。Mapper接口就相当于Dao接口。
- Mybatis框架底层是根据定义的Mapper接口使用动态代理的方式创建代理对象,代理对象就相当于DaoImpl。
- 程序员需要编写Mapper.xml映射文件(定义statement)
实现规范
- Mapper.xml映射文件与Mapper接口的名称必须一致
- Mapper.xml文件中的namespace与Mapper接口的路径一致
- Mapper接口的方法名和Mapper.xml中定义的每一个statement的id相同
- Mapper接口的方法的输入参数类型和Mapper.xml中定义的每一个statement中的parameterType类型一致
- Mapper接口的方法的输出参数类型和Mapper.xml中定义的每一个statement中的resultType类型一致
问题:mapper接口方法的参数只能有一个,系统是否不利于扩展维护?
可以使用包装类型的POJO满足不同的业务需求。
注意:UserMapper接口中参数可以是基本类型、原始POJO、VO,map等
实例
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">
<!--namespace:命名空间,
作用:对SQL进行分类化管理(隔离SQL)
注意:使用mapper代理的开发方式,namespace等同于mapper接口的全类名
-->
<mapper namespace="com.hpe.mybatis.mapper.UserMapper">
<!-- 在映射文件中可以配置很多SQL语句,不同的SQL语句有不同的标签
:select,updata,delete,insert
id:标识映射文件中的SQL,也可以称之为mapped statement
将来mybatis会把SQL语句封装到statement对象中
#{}:表示一个占位符,就相当于?
#{id}:其中的id表示接受的输入参数,id是参数名称
参数名称的要求:
1.如果输入参数是简单类型,参数名可以任意(可以是value可以是其他名称)
parameterType:指定输入参数类型(可以是完整全路径,可以是别名)
resultType:指定输出结果类型(执行SQL输出的结果所映射的Java对象类型)
-->
<!-- 1.根据用户id查询用户信息 -->
<select id="selectUserById" parameterType="int" resultType="com.hpe.mybatis.po.User">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 分局用户名和性别删除用户信息
如果在Mapper接口中的方法的参数有多个,这里不需要指定parameterType
方案一:将接口中方法的形参前面加上一个注解@param
方案二:在statement里面sql中的参数中使用索引实现
-->
<delete id="deleteUserByNameAndSex" >
DELETE FROM user WHERE username LIKE '%${username}%' AND sex = #{sex}
</delete>
<!-- 根据用户名性别查询信息(使用map)
注意:输入参数名称必须和map中的key名称相同
-->
<select id="findUserByMap" parameterType="map" resultType="com.hpe.mybatis.po.User">
SELECT * FROM user WHERE username LIKE '%${username}%' AND sex = #{sex}
</select>
</mapper>
接口
package com.hpe.mybatis.mapper;
import com.hpe.mybatis.po.User;
public interface UserMapper {
// 根据id查询用户信息
User selectUserById(int id) throws Exception;
// 根据姓名和性别删除用户信息(注解的方式)
int deleteUserByNameAndSex(@Param("username")String username,@Param("sex")String sex);
// 根据姓名和性别查询信息(使用map)
List<User> findUserByMap(Map<String, Object> map);
}
测试类:
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入Mybatis配置信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
// 根据id查询用户信息
@Test
public void testSelectUserById() throws Exception{
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建一个UserMapper的对象,mybatis自动化生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 调用userMapper中的方法
User user = userMapper.selectUserById(1);
System.out.println(user);
}
}
SqlMapConfig.xml
properties:属性
typeAliases:类型别名
plugins:插件
mappers:映射器
<?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="db.properties"></properties>
<!-- 别名定义 -->
<typeAliases>
<!-- 1.针对单个别名定义
type:类型路径
alias:别名
-->
<!-- <typeAlias type="com.hpe.mybatis.po.User" alias="User"/> -->
<!-- 2.批量定义别名:mybatis可以自动扫描包中的po类,自动定义别名
name:指定包名
别名:类名(首字母不区分大小写)。比如使用的时候可以用User或者user
-->
<package name="com.hpe.mybatis.po"/>
<!-- 可以指定多个package -->
</typeAliases>
<!-- mybatis的运行环境 -->
<!-- 将来和Spring整合之后,配置运行环境就废弃了 -->
<environments default="development">
<environment id="development">
<!-- 事务管理器:使用JDBC事务管理 -->
<transactionManager type="JDBC" />
<!-- 配置数据库连接池 -->
<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>
<mapper resource="mybatis/UserMapper.xml"></mapper>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>