了解ORM映射框架实现原理

阅读之前我们带着几个小问题去阅读下面文中的内容,本文以Hibernate框架理解ORM框架映射的实现原理。

  1. ORM映射框架中的entity(实体类)名字和表名不一致是如何与数据库表名对应的?
  2. entity(实体类)中的属性采用驼峰命名,以:userName,和数据库表中user_Name是如何对应的?
  3. 为什么Hibernate通过entity(实体类)就能完整的得到SQL语句?

下面我们完成一个ORM框架中entity(实体类) 与表字段不一致,却能生成完整的SQL语句的案例。

在使用Hibernate框架时,我们会创建实体类,创建字段去对应数据库表以及字段会使用到核心的两个注解,@Table@Column,其他的@Entity@Id等注解我们就先忽略,重点在原理上。

@Table 注解
该注解在使用时让实体类与表名对应,@Table("user_table"),这个注解其实就相当于起了一个别名的作用,我们可以尝试自定义一个注解模仿还原该注解。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTable {
	
	String value();
	
}

关于自定义注解,我就不做过多解释了。

@Column 注解
该注解用于实体类字段上,相当于该字段的别名,使其和数据库表中的列(Column即:列)对应。我们去自定义个和@Column注解相当的注解。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyColumn {

	String columnName();
	
	int columnLength();
	
	String columnType();
	
}

实体类

@MyTable("user_table")
public class User {

	@MyColumn(columnName="user_name",columnLength=5,columnType="String")
	private String userName;
	
	@MyColumn(columnName="user_age",columnLength=5,columnType="int")
	private int userAge;
	
	@MyColumn(columnName="user_id",columnLength=5,columnType="int")
	private int userId;
	
	@MyColumn(columnName="user_gender",columnLength=1,columnType="int")
	private int gender;

	// 省略get/set/构造/toString等方法
	
}

现在我们完成了两个核心的注解,实体类也和数据库表对应了,那么下一步就是通过实体类生成SQL

生成SQL
想要生成完整的SQL,就需要拿到表名,字段名。刚才在通过我们自定义的两个注解和数据库表已经做了一个映射了。那么我们怎么才能拿到呢?我们可以通过 反射 !

import java.lang.reflect.Field;

public class MyOrmTest {

	public static void main(String[] args) throws ClassNotFoundException {
		System.out.println(selectUserTable());
	}

	public static String selectUserTable() throws ClassNotFoundException {

		// 通过反射获取到Class
		Class<?> classForName = Class.forName("orm.test.User");
		// 获取注解@MyTable
		MyTable table = classForName.getAnnotation(MyTable.class);
		// 获取到类的所有字段
		Field[] Fields = classForName.getDeclaredFields();

		// 拼接SQL
		StringBuffer sb = new StringBuffer();
		sb.append(" select ");

		// 获取注解@MyTable的值
		String tableName = table.value();

		// 迭代类中所有字段,获取字段上注解@MyColumn的值并拼接SQL
		for (int i = 0; i < Fields.length; i++) {
			Field field = Fields[i];
			MyColumn column = field.getAnnotation(MyColumn.class);
			sb.append(" " + column.columnName() + " ");
			if (i == Fields.length - 1) {
				sb.append(" from ");
			} else {
				sb.append(",");
			}
		}
		sb.append(" " + tableName);

		return sb.toString();
	}
}

ORM很多的细节,比如字段类型的处理等等,就不去了解了,我们了解ORM和核心原理即可。

发布了13 篇原创文章 · 获赞 32 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/QingHe97/article/details/103837236