- 前言
- 一、ORM框架是什么?
- 二、讲解
- 1.创建表和字段的对象映射
- 2.编写解析类
- 3.测试
- 4.持久性保证
- 总结
前言
做后端项目经常要引入持久层ORM框架,相对于直接 *** 作JDBC来说,利用Mybatis,Hibernate这样的框架能够加快我们的开发进度.引入ORM框架带来的三个好处有:
- 1.简单 - 避免繁琐的编程语句
2.精确 -只要对象定义好了,不易出现sql层面的错误
3.持久性 -避免了频繁写sql带来的连接建立与释放。
下面带大家写一个简易的ORM框架,顺便讲解ORM框架的底层原理(楼主实习面试被问过这个问题/(ㄒoㄒ)/~~)
一、ORM框架是什么?ORM全称为:Object Relational Mapping对象关系映射,是一种程序对象与数据库中的数据(存储模型和内存模型)的映射,
就是把映射关系以注解的方式放在实体类中,利用反射动态加载类中的对象和方法并生产sql语句,
为了对映射关系进行配置,可以用xml 配置的方式,或者是注解的方式,本质都是一样的,表字段过多是建议用xml,但注解讲解起来更加清晰。就是把映射关系以注解的方式放在实体类中,
首先我们创建一个数据库表如下
表名 | user_table |
---|---|
字段1 | id |
字段2 | name |
然后利用以下两个自定义注解创建表和字段的映射
package DIY_ORM;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义Table注解
*/
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Table {
String value() default "";
}
package DIY_ORM;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义Column注解
*/
@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
String value() default "";
}
然后创建个user类
package DIY_ORM;
//实体类
@Table("user_table")
public class User{
@Column("id")
private String id;
@Column("name")
private String name;
public User(String id,String name)
{
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
以上过程也可以写成xml就是
<hibernate-mapping>
<class name="User" table="user_table">
<id name="id">
<column name="id"/>
</id>
<property name="name">
<column name="name"/>
</property>
</class>
</hibernate-mapping>
可以看到xml文件是更加简洁的。
2.编写解析类以上过程完成后我们需要创建一个类用于对关系映射进行解析,转换为sql语句,由于事先不知道类名称,故可以用反射实现类的动态加载。
package DIY_ORM;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class AnnotationParser {
//利用数据库的实体类对象生成sql语句
public static String assembleSqlFromObj(Object obj) {
Table table = obj.getClass().getAnnotation(Table.class); //利用反射得到注解
StringBuffer sbSql = new StringBuffer();
String tableName = table.value();
//System.out.println("tablename"+tableName);
sbSql.append("select * from " + tableName + " where 1=1 ");
Field[] fileds = obj.getClass().getDeclaredFields(); //利用反射得到类中的对象id,name
for (Field f : fileds) {
String fieldName = f.getName();
String methodName = "get" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
try {
Column column = f.getAnnotation(Column.class);
if (column != null) {
Method method = obj.getClass().getMethod(methodName); //利用反射执行类的getId,getName方法
//System.out.println(method);得到方法名称
Object v = method.invoke(obj); //执行get方法并返回
if (v != null) {
sbSql.append(" and " + column.value() + "=" + v.toString() + " ");
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
return sbSql.toString();
}
}
3.测试
编写个测试函数测试一下,可以看到我们成功的由对象得到了sql语句,接下来调用jdbc执行就行拉。
package DIY_ORM;
public class OrmTest {
public static void main(String[] args) {
User testDto = new User("1", "wangwang");
String sql = AnnotationParser.assembleSqlFromObj(testDto);
System.out.println(sql);
}
}
4.持久性保证
以上实现还有一个问题,在成熟的框架中都有selsessionFactory类实现持久化,读取配置类,生产sqlsession,对数据库增删改查,它类似于一个连接池管理类,所以我们还要再写一个连接池,并改写代码。
以下连接池讲解来自作者:乘风破浪的姐姐
链接:https://www.jianshu.com/p/70a4320e5f75
DBCP 是一个开源的连接池,是Apache Common成员之一,在企业开发中也比较常见,tomcat内置的连接池。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
应用程序应在系统中增加如下两个 jar 文件:
- mysql-connector-java-5.1.37-bin.jar:数据库驱动
- commons-dbutils-1.6.jar:提供QueryRunner类方便进行增删改查 *** 作
- commons-dbcp-1.4.jar:连接池的实现
- commons-pool-1.5.6.jar:连接池实现的依赖库,提供高效的数据库连接池技术
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
public class JDBCUtils{
//创建出BasicDataSource类对象
private static BasicDataSource datasource = new BasicDataSource();
//静态代码块,对象BasicDataSource对象中的配置,自定义
static{
//数据库连接信息,必须的
datasource.setDriverClassName("com.mysql.jdbc.Driver");
datasource.setUrl("jdbc:mysql://localhost:3306/user");
datasource.setUsername("root");
datasource.setPassword("123");
//对象连接池中的连接数量配置,可选的
datasource.setInitialSize(10);//初始化的连接数
datasource.setMaxActive(8);//最大连接数量
datasource.setMaxIdle(5);//最大空闲数
datasource.setMinIdle(1);//最小空闲
}
//定义静态方法,返回BasicDataSource类的对象
public static DataSource getDataSource(){
return datasource;
}
}
* 测试写好的工具类,
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import cn.itcast.jdbcutils.JDBCUtils;
public class QueryRunnerDemo{
public static void main(String[] args) {
User testDto = new User("1", "wangwang");
String sql = AnnotationParser.assembleSqlFromObj(testDto);
select(sql);
}
//QueryRunner类对象,写在类成员位置
private static QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
//数据表查询
public static void select(String sql){
try{
List<Object[]> list = qr.query(sql, new ArrayListHandler());
for(Object[] objs : list){
for(Object obj : objs){
System.out.print(obj+"\t");
}
System.out.println();
}
}catch(SQLException ex){
throw new RuntimeException("数据查询失败");
}
}
}
总结
以上,DIY_Orm的关键在于:
- 利用注解或者xml实现对象关系映射
- 利用解析类中的反射实现加载类中的对象和方法,实现sql语句的拼装
- 利用数据库连接池实现持久化。
若有不足,欢迎评论区补充
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)