网络知识 娱乐 Mybatis 源码深度解析-常用工具类

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

大纲

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

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

//使用ScriptRunner 运行.sql脚本文件nConnection connection = DriverManager.getConnection("jdbc:hsqldb:mem:mybatis", "sa", "");nScriptRunner scriptRunner = new ScriptRunner(connection);nReader resource = Resources.getResourceAsReader("create-table.sql");nscriptRunner.runScript(resource);nn//同时还有一个是专门运行sql 语句的SqlRunnernSqlRunner sqlRunner = new SqlRunner(connection);nList<Map<String, Object>> list = sqlRunner.selectAll("select * from user where id =?", Integer.valueOf(1));nSystem.out.println(JSON.toJSONString(list));


  • 定义两个实体类,后续示例都需要用到,(使用了 lombok 注解生成 getter,setter)

@Datan@AllArgsConstructornpublic class User {n List<Order> orders;n String name;n Integer age;n}nn@Datan@AllArgsConstructornpublic class Order {n String orderNo;n String goodsName;n}


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

List<Order> orders = new ArrayList<>();norders.add(new Order("order1234", "<mybatis 源码深度解析>图书"));norders.add(new Order("order1234", "test val"));nnUser user = new User(orders, "Axing", 18);nn//操作 user 对象nMetaObject metaObject = SystemMetaObject.forObject(user);n//获取第一笔订单的商品名称nSystem.out.println(metaObject.getValue("orders[0].goodsName"));//<mybatis 源码深度解析>图书n//获取第二笔订单的商品名称nSystem.out.println(metaObject.getValue("orders[1].goodsName"));nn//为属性设置值nmetaObject.setValue("orders[0].goodsName", "metaObject.setValue 设置的值");nSystem.out.println(metaObject.getValue("orders[0].goodsName"));//metaObject.setValue 设置的值nn//判断对象是否有 orderNo 属性nSystem.out.println(metaObject.hasGetter("orderNo"));//falsenSystem.out.println(metaObject.hasGetter("name"));//true

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

MetaClass metaClass = MetaClass.forClass(Order.class, new DefaultReflectorFactory());nn//获取所有 Getter 方法的属性名nString[] getterNames = metaClass.getGetterNames();nSystem.out.println(JSON.toJSONString(getterNames));nn//是否有 getter 方法nSystem.out.println(metaClass.hasGetter("orderNo"));//truenn//获取 调用 Getter 方法nInvoker orderNoInvoker = metaClass.getGetInvoker("orderNo");nOrder order1234 = new Order("order1234", "<mybatis 源码深度解析>图书");nObject orderNoVal = orderNoInvoker.invoke(order1234, null);nSystem.out.println(orderNoVal);

4 ObjectFactory 工厂类

  • ObjectFactory是mybats 中的对象工厂,默认实现类为 DefaultObjectFactory
  • DefaultObjectFactory 支持通过接口方式创建对象
  • mybatis 每次创建 Mapper映射结果对象的新实例时,都会使用一个对象工厂(ObjectFactory)实例来完成

@Testnpublic void ObjectFactory() {n ObjectFactory objectFactory = new DefaultObjectFactory();n List list = objectFactory.create(List.class);n list.addAll(Arrays.asList(1, 2, 3));n System.out.println(list);n}

  • 使用ObjectFactory实例创建 Mapper 映射结果的目的,是为了提供一种扩展机制
  • 自定义一个ObjectFactory, 1 继承DefaultObjectFactory 2 重写create()方法,如下

public class CustomObjectFactory extends DefaultObjectFactory {n @Overriden public <T> T create(Class<T> type) {n if (type.equals(User.class)) {n User user = (User) super.create(type);n user.age = 18;n return (T) user;n }n return super.create(type);n }n}

5 ProxyFactory 代理工厂类

  • ProxyFactory 是 Mybatis 中的代理工厂,主要是为了创建动态代理对象
  • ProxyFactory 有两种不同的实现,分别为: CglibProxyFactory 和 JavassistProxyFactory
  • ProxyFactory 在 mybatis中主要是为了实现懒加载功能

@Testnpublic void ProxyFactory() {n ProxyFactory proxyFactory = new JavassistProxyFactory();n Order order1234 = new Order("order1234", "<mybatis 源码深度解析>图书");n ObjectFactory objectFactory = new DefaultObjectFactory();nn //使用ProxyFactory 对象创建订单 order1234的代理对象n Object proxyOrder = proxyFactory.createProxy(order1234,n mock(ResultLoaderMap.class),n mock(Configuration.class),n objectFactory,n Arrays.asList(String.class, String.class),n Arrays.asList(order1234.orderNo, order1234.goodsName)n );nn System.out.println(proxyOrder.getClass());n System.out.println(((Order) proxyOrder).orderNo);n}