这里写目录标题
一、完整代码
Mybatis核心原理:对象代理
我们只需要按照原生Java的使用方式进行数据库操作即可,Mybatis内部对原生对象进行加强处理得到一个对应的代理对象,我们通过当前对象方法调用进行数据库操作时,实质是Mybatis内部生成的代理对象内部的统一方法在进行工作。
举例,我们通过UserMapper接口声明一个userMapper对象,Mybatis内部验证发现userMapper对象被mapper注解修饰,因此对该userMapper对象进行加强处理得到一个对应的代理对象,也就是我们真正拿到的userMapper对象是一个代理对象。后续在通过userMapper调用selectAll方法时,Mybatis内部对其进行拦截,统一执行内部的invoke方法,真正实现JDBC操作的过程是通过invoke方法实现的。
1.实体类User
@Data
public class User {
private Integer uid;
private String username;
private String password;
private String avatarUrl;
public User(){
System.out.println("User()无参构造");
}
}
2.Mapper接口UserMapper
public interface UserMapper {
@Select("select * from users")
List<User> selectAll();
}
此处使用的Select注解是我们自定义的注解,其中的value用于保存该注解内部的SQL语句:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
String value(); // 存储对应的SQL语句
}
3.代理对象
原生Java对象一旦生成代理对象,则通过该对象调用原生方法时,实质会被拦截执行invoke方法
public class ProxyObject implements InvocationHandler {
//InvocationHandler:调用管理,所有调用都会进入invoke方法
private DataSource dataSource; // 数据源
{
MysqlDataSource mysqlDataSource=new MysqlDataSource();
// 数据库参数设置
mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/sys25?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai");
mysqlDataSource.setUser("root");
mysqlDataSource.setPassword("123456");
dataSource=mysqlDataSource;
}
@Override
// method:指的是原生User对象所调用的方法
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
// 获取注解信息
Select annotation = method.getAnnotation(Select.class);
String sql = annotation.value(); // 对应的sql语句
// 真正执行JDBC查询操作
List<User> userList=new ArrayList<>();
try(Connection connection=dataSource.getConnection()){
try (PreparedStatement statement=connection.prepareStatement(sql)){
try (ResultSet resultset=statement.executeQuery()){
while (resultset.next()){
User user=new User();
int uid = resultset.getInt("uid");
String username=resultset.getString("username");
String password=resultset.getString("password");
String avatar_url=resultset.getString("avatar_url");
user.setUid(uid);
user.setUsername(username);
user.setPassword(password);
user.setAvatarUrl(avatar_url);
userList.add(user);
}
}
}
}
return userList;
}
}
4.程序入口
public class Main {
public static void main(String[] args) {
UserMapper userMapper=getByString(); // 其实获取的是一个代理对象,由Mybatis内部进行加强处理得到
List<User> userList = userMapper.selectAll();
for (User user:userList){
System.out.println(user);
}
}
public static UserMapper getByString(){
return (UserMapper)Proxy.newProxyInstance(
Main.class.getClassLoader(),
new Class[]{
UserMapper.class},
new ProxyObject()
);
}
}
查询结果如下: