【深入理解MyBatis】- 06Mybatis 源对象MetaObject使用

MetaObject简介

MetaObject对象是Mybatis框架用于访问对象属性的工作类,底层实现为java的反射基础。目前只支持JavaBean、Collection、Map三种类型对象访问,也可以自定义其他类型

Bean访问例子

public class BeanTest {
	public static void main(String[] args) {
		Person person = new Person();
		MetaObject metaObject = SystemMetaObject.forObject(person);
		metaObject.setValue("id", 34567);
		metaObject.setValue("name", "aaa");
		System.out.println(metaObject.getValue("id"));
		System.out.println(metaObject.getValue("name"));
	}
	
	static class Person {
		int id;
		String name;
		public int getId() {
			return id;
		}
		public void setId(int id) {
			this.id = id;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		
	}
}

测试结果

34567
aaa

Collection访问例子

public class CollectionTest {
	public static void main(String[] args) {
		Person person = new Person();
		person.getList().add("aaaa");
		person.getList().add("bbbb");
		person.getList().add("cccc");
		MetaObject metaObject = SystemMetaObject.forObject(person);
		System.out.println(metaObject.getValue("list[1]"));
	}
	static class Person {
		List<String> list = new ArrayList<>();

		public List<String> getList() {
			return list;
		}

		public void setList(List<String> list) {
			this.list = list;
		}
	}
}

测试结果

bbbb

Map访问例子

public class MapTest {
	public static void main(String[] args) {
		Map<String, String> map = new HashMap<>();
		map.put("name", "zhangsan");
		MetaObject metaObject = SystemMetaObject.forObject(map);
		System.out.println(metaObject.getValue("name"));
	}
}

测试结果

zhangsan

MetaObject结构

在这里插入图片描述
MetaObject对象主要由于下来对象组成

  • Object原对象:持有原始对象
  • ObjectFactory对象工厂:负责创建对象,对象可能层层嵌套,都对象为null时,需要通过对象工厂创建
  • ObjectWrapper包装对象:增强原始对象功能
  • ObjectWrapperFactory包装对象工厂
  • ReflectorFactory反射器工厂:Class元信息的封装

接下来,我们将分三部分来讲解

  1. 反射器类 :【深入理解MyBatis】- 07Mybatis 反射器Reflector源码
  2. 对象包装类
  3. 对象工厂

默认对象工厂类DefaultObjectFactory,逻辑也比较简单

  public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
	  // 做接口转换,将接口绑定上默认实现类,如Map->HashMap等
    Class<?> classToCreate = resolveInterface(type);
    // 实例化类classToCreate
    return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
  }

核心方法instantiateClass,对应获取构造器为constructor = type .getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));

  /**
   * type: 对象class
   * constructorArgTypes: 参数class列表
   * constructorArgs: 参数值列表
   */
	private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
		try {
			Constructor<T> constructor;
			if (constructorArgTypes == null || constructorArgs == null) {
				constructor = type.getDeclaredConstructor();
				if (!constructor.isAccessible()) {
					constructor.setAccessible(true);
				}
				return constructor.newInstance();
			}
			constructor = type
					.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
			if (!constructor.isAccessible()) {
				constructor.setAccessible(true);
			}
			return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
		} catch (Exception e) {
			StringBuilder argTypes = new StringBuilder();
			if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
				for (Class<?> argType : constructorArgTypes) {
					argTypes.append(argType.getSimpleName());
					argTypes.append(",");
				}
				argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,
			}
			StringBuilder argValues = new StringBuilder();
			if (constructorArgs != null && !constructorArgs.isEmpty()) {
				for (Object argValue : constructorArgs) {
					argValues.append(String.valueOf(argValue));
					argValues.append(",");
				}
				argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,
			}
			throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes
					+ ") or values (" + argValues + "). Cause: " + e, e);
		}
	}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring整合MyBatis-Plus的步骤如下: 1. 引入依赖:在pom.xml文件中添加以下依赖 ```xml <dependencies> <!--Spring Boot MyBatis Plus Starter--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!--MyBatis Plus 代码生成器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!--MyBatis Plus 分页插件--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-extension</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!--MyBatis Plus 自动填充插件--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-extension</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!--MyBatis Plus SQL注入器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-extension</artifactId> <version>${mybatis-plus.version}</version> </dependency> </dependencies> ``` 2. 配置数据:在application.yml文件中添加数据信息 ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: root driver-class-name: com.mysql.jdbc.Driver ``` 3. 配置MyBatis-Plus:在application.yml文件中添加MyBatis-Plus配置信息 ```yaml mybatis-plus: # 实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.example.demo.entity # 显示SQL语句 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 分页插件配置 page: helper-dialect: mysql # 开启分页 reasonable: true # 每页最多显示条数,默认500条 max-limit: 10000 # 自动填充配置 global-config: db-config: # 自动填充创建时间 meta-object-handler: com.baomidou.mybatisplus.extension.handlers.MybatisDefaultMetaObjectHandler ``` 4. 创建实体类:创建Java Bean实体类,使用MyBatis-Plus注解定义表名和字段名 ```java @Data @TableName("user") public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; private String email; private Date createTime; private Date updateTime; } ``` 5. 创建Mapper接口:创建Mapper接口,并继承MyBatis-Plus的BaseMapper接口 ```java public interface UserMapper extends BaseMapper<User> { } ``` 6. 测试:编写测试类,测试MyBatis-Plus的CRUD操作 ```java @SpringBootTest class MybatisPlusDemoApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads() { } @Test void testInsert() { User user = new User(); user.setName("Tom"); user.setAge(20); user.setEmail("tom@163.com"); int result = userMapper.insert(user); System.out.println("插入结果:" + result); } @Test void testSelect() { List<User> userList = userMapper.selectList(null); System.out.println("查询结果:" + userList); } @Test void testUpdate() { User user = new User(); user.setId(1L); user.setName("Jack"); int result = userMapper.updateById(user); System.out.println("更新结果:" + result); } @Test void testDelete() { int result = userMapper.deleteById(1L); System.out.println("删除结果:" + result); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值