动态代理的实现
MyBatis的Mapper接口是一种用于描述数据库操作的接口,它通过注解或XML配置文件定义了对应的SQL语句和参数映射。在运行时,MyBatis会根据Mapper接口的定义生成动态代理对象,实现接口中定义的方法,并且在方法执行时根据SQL语句和参数映射执行数据库操作。
以下是一个简单的示例,演示了如何定义一个Mapper接口以及如何使用它进行数据库操作
定义Mapper接口
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User selectUserById(int id);
@Insert("INSERT INTO user (name, age) VALUES (#{name}, #{age})")
void insertUser(User user);
}
配置Mapper接口
在MyBatis的配置文件中,需要配置Mapper接口的路径以及对应的XML文件(如果使用XML配置方式):
<configuration>
<mappers>
<mapper class="com.example.mapper.UserMapper"/>
</mappers>
</configuration>
使用Mapper接口
在代码中,代理对象的方法名、参数类型和个数等信息,都会被传递到MyBatis的SqlSession对象中,SqlSession对象会根据这些信息找到相应的Mapper XML文件中的SQL语句,并调用其中定义的方法进行数据库操作:
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
//动态代理生成一个实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUserById(1);
System.out.println(user);
User newUser = new User();
newUser.setName("Alice");
newUser.setAge(20);
userMapper.insertUser(newUser);
sqlSession.commit();
}
在运行时,MyBatis会根据UserMapper接口的定义生成一个动态代理对象,实现其中的方法。例如,当调用userMapper.selectUserById(1)时,MyBatis会解析@Select("SELECT * FROM user WHERE id = #{id}")注解,并根据参数id执行相应的数据库操作,最终返回查询结果。动态SQL的生成也是在代理对象中完成的.
使用动态代理的好处是,它可以让开发人员在不编写实现类的情况下使用接口。这样,开发人员可以专注于定义接口,而MyBatis则可以生成实现这些接口的类。
需要注意的是,Mapper接口的定义必须与SQL语句和参数映射一一对应,否则会导致运行时错误。此外,Mapper接口也可以通过XML配置文件定义SQL语句和参数映射,这种方式相对更灵活,但也更容易出错。
sqlSession.getMapper()的代码逻辑
SqlSession是 MyBatis 框架中的核心类之一,用于操作数据库。getMapper 方法是 SqlSession 接口中的一个方法,用于获取一个 DAO 接口的实现类对象。getMapper 方法的代码逻辑如下:
接收一个 Class 类型的参数,表示需要获取实现类对象的 DAO 接口类。
通过调用 Configuration 对象的 getMapperRegistry 方法获取一个 MapperRegistry 对象,用于管理所有的 Mapper。
通过调用 MapperRegistry 对象的 getMapper 方法获取一个 MapperProxyFactory 对象。
通过调用 MapperProxyFactory 对象的 newInstance 方法,创建一个代理对象。
返回代理对象。
在步骤 3 中,getMapper 方法会先从 knownMappers 缓存中查找是否已经存在对应的 Mapper,如果已经存在,则直接返回缓存中的 Mapper。如果不存在,则创建一个新的 MapperProxyFactory 对象,并添加到 knownMappers 缓存中。
在步骤 4 中,newInstance 方法会创建一个代理对象,该代理对象实现了 DAO 接口,并重写了其中的所有方法。当代理对象的方法被调用时,会先获取一个 MappedStatement 对象,该对象表示了需要执行的 SQL 语句和参数信息。然后通过 SqlSession 对象的 selectList、selectOne、insert、update、delete 等方法执行 SQL 语句,最后返回查询结果或受影响的行数等信息。