Mybatis 源码深度解析-常用工具类

大纲

  • ScriptRunner 是脚本运行工具类,可以运行 sql文件
  • MetaObject 是 mybatis 的反射工具类,用于获取和设置对象属性值
  • metaClass 通过反射获取类的相关信息
  • ObjectFactory 是mybats 中的对象工厂,默认实现类为 DefaultObjectFactory
  • ProxyFactory 是 Mybatis 中的代理工厂,主要是为了创建动态代理对象

1 ScriptRunner 运行 sql文件,使用示例

//使用ScriptRunner 运行.sql脚本文件
Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:mybatis", "sa", "");
ScriptRunner scriptRunner = new ScriptRunner(connection);
Reader resource = Resources.getResourceAsReader("create-table.sql");
scriptRunner.runScript(resource);

//同时还有一个是专门运行sql 语句的SqlRunner
SqlRunner sqlRunner = new SqlRunner(connection);
List> list = sqlRunner.selectAll("select * from user where id =?", Integer.valueOf(1));
System.out.println(JSON.toJSONString(list));


  • 定义两个实体类,后续示例都需要用到,(使用了 lombok 注解生成 getter,setter)
@Data
@AllArgsConstructor
public class User {
  List orders;
  String name;
  Integer age;
}

@Data
@AllArgsConstructor
public class Order {
  String orderNo;
  String goodsName;
}


2 MetaObject 是 mybatis 的反射工具类,用于获取和设置对象属性值

List orders = new ArrayList<>();
orders.add(new Order("order1234", "图书"));
orders.add(new Order("order1234", "test val"));

User user = new User(orders, "Axing", 18);

//操作 user 对象
MetaObject metaObject = SystemMetaObject.forObject(user);
//获取第一笔订单的商品名称
System.out.println(metaObject.getValue("orders[0].goodsName"));//图书
//获取第二笔订单的商品名称
System.out.println(metaObject.getValue("orders[1].goodsName"));

//为属性设置值
metaObject.setValue("orders[0].goodsName", "metaObject.setValue 设置的值");
System.out.println(metaObject.getValue("orders[0].goodsName"));//metaObject.setValue 设置的值

//判断对象是否有 orderNo 属性
System.out.println(metaObject.hasGetter("orderNo"));//false
System.out.println(metaObject.hasGetter("name"));//true

3 metaClass 通过反射获取类的相关信息

MetaClass metaClass = MetaClass.forClass(Order.class, new DefaultReflectorFactory());

//获取所有 Getter 方法的属性名
String[] getterNames = metaClass.getGetterNames();
System.out.println(JSON.toJSONString(getterNames));

//是否有 getter 方法
System.out.println(metaClass.hasGetter("orderNo"));//true

//获取 调用 Getter 方法
Invoker orderNoInvoker = metaClass.getGetInvoker("orderNo");
Order order1234 = new Order("order1234", "图书");
Object orderNoVal = orderNoInvoker.invoke(order1234, null);
System.out.println(orderNoVal);

4 ObjectFactory 工厂类

  • ObjectFactory是mybats 中的对象工厂,默认实现类为 DefaultObjectFactory
  • DefaultObjectFactory 支持通过接口方式创建对象
  • mybatis 每次创建 Mapper映射结果对象的新实例时,都会使用一个对象工厂(ObjectFactory)实例来完成
@Test
public void ObjectFactory() {
  ObjectFactory objectFactory = new DefaultObjectFactory();
  List list = objectFactory.create(List.class);
  list.addAll(Arrays.asList(1, 2, 3));
  System.out.println(list);
}
  • 使用ObjectFactory实例创建 Mapper 映射结果的目的,是为了提供一种扩展机制
  • 自定义一个ObjectFactory, 1 继承DefaultObjectFactory 2 重写create()方法,如下
public class CustomObjectFactory extends DefaultObjectFactory {
  @Override
  public  T create(Class type) {
    if (type.equals(User.class)) {
      User user = (User) super.create(type);
      user.age = 18;
      return (T) user;
    }
    return super.create(type);
  }
}

5 ProxyFactory 代理工厂类

  • ProxyFactory 是 Mybatis 中的代理工厂,主要是为了创建动态代理对象
  • ProxyFactory 有两种不同的实现,分别为: CglibProxyFactory 和 JavassistProxyFactory
  • ProxyFactory 在 mybatis中主要是为了实现懒加载功能
@Test
public void ProxyFactory() {
  ProxyFactory proxyFactory = new JavassistProxyFactory();
  Order order1234 = new Order("order1234", "图书");
  ObjectFactory objectFactory = new DefaultObjectFactory();

    //使用ProxyFactory 对象创建订单 order1234的代理对象
    Object proxyOrder = proxyFactory.createProxy(order1234,
      mock(ResultLoaderMap.class),
      mock(Configuration.class),
      objectFactory,
      Arrays.asList(String.class, String.class),
      Arrays.asList(order1234.orderNo, order1234.goodsName)
    );

  System.out.println(proxyOrder.getClass());
  System.out.println(((Order) proxyOrder).orderNo);
}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章