写个自己的ORM框架

ORM框架将数据库中的关系数据转化为程序对象,简化了数据库操作。本文介绍了ORM的基本原理,核心原则,以及通过Java实现自定义ORM框架的过程,包括使用注解进行映射,并通过解析注解生成SQL语句,实现对象与数据库表之间的交互。

ORM框架是什么

对象关系映射(Object Relational Mapping),目前数据库是关系型数据库 , ORM 主要是把数据库中的关系数据映射成为程序中的对象。ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。Java典型的ORM中间件有:Hibernate,Mybatis等。 这样能够让程序员更多的关注业务编程,而不用浪费在SQL语句的编写上。

映射方式:注解,xml

ORM的方法论基于三个核心原则:
  · 简单:以最基本的形式建模数据。
  · 传达性:数据库结构被任何人都能理解的语言文档化。
  · 精确性:基于数据模型创建正确标准化了的结构。

ORM技术特点:
1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。

下面就开始自己ORM框架编写,源码可在github上找到:

首先在数据库创建一张user_info表:在这里插入图片描述

有id,name,birthday三个字段。我们要对数据库这张表进行操作的话,就要创建一个与它对应的entity对象,通过操作实体类对象达到数据库表的操作。

@Table("user_info")
public class UserInfo {

	@Column
	private Integer id;
	@Column
	private String name;
	@Column
	private Date birthday;
	
	
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	
	
}

那么我们怎么让表和对象产生对应关系呢?我们可以通过在entity对象上添加注解,让对象和数据库表关系映射。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
	String value() default "";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
	String value() default "";
}

映射关系已经有了,接下来就来操作对象吧

public interface UserDao {
	int insert(UserInfo userInfo);
}
public class UserDaoImpl implements UserDao {
	@Override
	public int insert(UserInfo userInfo) {
		return session.insert(userInfo);
	}
}

你会发现根本不行,因为这个映射关系只是我们自己定义的,接下来就是这个ORM框架核心的部分了,就是让我们自定义的注解能够生效,生成想要的sql语句:

public interface SqlSession {
	<T> int insert(T entity);
}
public class SqlSessionImpl implements SqlSession {

	private DataSource dataSource;
	
	public SqlSessionImpl(){
		this.dataSource = new DataSourceImpl();
	}

	@Override
	public <T> int insert(T entity) {
		int row = 0;
		if(entity == null){
			throw new ORMException("实体对象为空");
		}
		
		//构建SQL语句
		StringBuilder sql = new StringBuilder();
		//参数列表
		List<Object> parameters = new ArrayList<>();
		
		builderSqlByEntity(entity,sql,parameters);
		
		try(Connection connect = dataSource.getDataSource();
				PreparedStatement statement = connect.prepareStatement(sql.toString())){
			if(parameters.size() > 0){
				for(int i = 0; i < parameters.size(); i++){
					statement.setObject(i+1, parameters.get(i));
				}
			}
			//执行SQL
			row = statement.executeUpdate();
		}catch(Exception e){
			throw new ORMException("执行SQL语句出错:" + e.getMessage());
		}
		
		
		return row;
	}
	
	
	
	@SuppressWarnings("unused")
	private<T> void builderSqlByEntity(T entity,StringBuilder sql,List<Object> parameters){
		//根据实体对象生成SQL语句
		Class<?> clazz = entity.getClass();
		
		//如果table没有指定名字,则用类名代替
		String tableName = clazz.getSimpleName();
		if(clazz.isAnnotationPresent(Table.class)){
			Table table = clazz.getAnnotation(Table.class);
			if(!"".equals(table.value())){
				tableName = table.value();
			}
		}
		
		sql.append("insert into ").append(tableName).append("(");
		
		Field[] fields = clazz.getDeclaredFields();
		try{
			for(Field field : fields){
				String columnName = field.getName();
				if(field.isAnnotationPresent(Column.class)){
					Column column = field.getAnnotation(Column.class);
					if(!"".equals(column.value())){
						columnName = column.value();
					}
				}
				
				//属性描述器
				PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz);
				Method method = descriptor.getReadMethod();
				Object object = method.invoke(entity);
				
				if(object != null){
					sql.append(columnName + ",");
					parameters.add(object);
				}
			}
			
			sql.deleteCharAt(sql.length()-1).append(") values (");
			for(Object obj : parameters){
				sql.append("?,");
			}
			sql.deleteCharAt(sql.length()-1).append(")");
			System.out.println(sql);
			
		}catch(Exception e){
			throw new ORMException("执行SQL语句出错:" + e.getMessage());
		}
		
	}

}
public class UserDaoImpl implements UserDao {

	private SqlSession session = new SqlSessionImpl();
	
	@Override
	public int insert(UserInfo userInfo) {
		
		return session.insert(userInfo);
	}

}

这样我们就能通过在entity对象上添加自定义的注解与数据库表产生映射关系,操作实体对象就能对表进行增删改查的操作。自己编写的简单ORM框架就完成了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值