ORM ( 对象关系 Object Relation Mapping )
用 Java 对象来描述对象与对象之间的关系和数据内容
Hibernate Mybatis JPA SpringJDBC 对比
- Hibernate 全自动档 不需要写一句SQL语句、烧油(牺牲性能)
- MyBatis 手自一体(半自动) 支持单表映射,多表关联需要配置,轻量级一些
- SpringJDBC 手动挡 包括SQL语句,映射都是要自己实现的(最省油的)
喜欢轻装上阵 Spring 本来就是 万能胶 IOC
/ AOP
/ DI
/ MVC
/ JDBC
/ BigData
/ Cloud
/ Boot
因为 Spring 形成一个 生态
为什么要自己写 ORM 框架?
- 1、解决实际的业务问题(根据业务需要)
- 2、自定义需求,如果要直接第三方开源框架的话,需要进行二次开发
- 3、解决团队成员之间水平参差不齐的问题
- 4、可以实现统一的管理、监控、排错等等一系列底层操作
实际业务需要:
- 大数据监测系统:
- 数据吞吐量大
- 数据存储方式多样化
- 数据源需要频繁切换
- API无法统一
ORM 框架的设计图解:
最底层的类
1、统一方法名
- select
- insert
- delete
- update
find / get / load / query
//约定 如果是删、改,以ID作为唯一的检索条件,如果没有ID,那么要先查出来得到ID
2、统一参数
如果是做条件查询 QueryRule
(自己封装) 批量更新和插入 ,方法名以All结尾 参数为List 删、改、插一条数据 ,参数用 T
3、统一返回结果 所有的分页操作返回 Page
所有的集合查询返回 List
所有的单条查询返回 T
所有的ID采用 Long
类型
所有的删除、修改、增加操作返回 boolean
对外输出都用 ResultMsg
java extends core common
javax.core.common.utils
操作工具包 javax.core.common.config
统一配置 javax.core.common.doc
文档生成
javax.core.common.jdbc
JDBC依赖 javax.core.common.redis
Redis javax.core.common.mongodb
MongoDB javax.core.common.hbase
Hbase
只要是Spring相关的配置都以 application- 开头 建议不要把所有的东西在一个文件中,这样不便于团队开发的维护
aop
配置切面,代理规则的 beans
配置单例对象的 common
配置通用的配置 context
主入口 db
数据库相关 web
跟页面打交道的、拦截器、过滤器、监听器、模板
JDBC 例子:
java
import com.darian.spring.orm.demo.model.Member;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by Tom on 2018/5/9.
*/
public class JdbcTest {
public static void main(String[] args) {
// List<?> result = select(Member.class);
Member condition = new Member();
condition.setName("tom");
// condition.setAge(20);
List<?> result = select(condition);
System.out.println(Arrays.toString(result.toArray()));
}
//我框架问世的时候,你的Member类都还没有从石头缝里蹦出来
private static List<?> select(Object condition){
try{
Class<?> entityClass = condition.getClass();
//1、加载驱动类
Class.forName("com.mysql.jdbc.Driver");
//2、建立连接
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/gupaoedu_demo?characterEncoding=UTF-8&rewriteBatchedStatements=true","root","123456");
Table table = entityClass.getAnnotation(Table.class);
//3、创建语句开始事务
//为了简便,暂时用select * from 代替,不要说我不严谨,OK?
String sql = "select * from " + table.name();
StringBuffer where = new StringBuffer(" where 1=1 ");
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object value = field.get(condition);
if(null != value) {
Class<?> clazz = field.getType();
if(String.class == clazz){
where.append(" and " + field.getName() + " = '" + value + "'");
}else{
where.append(" and " + field.getName() + " = " + value);
}
}
}
System.out.println(sql + where.toString());
PreparedStatement pstmt = conn.prepareStatement(sql + where.toString());
//4、执行语句集
ResultSet rs = pstmt.executeQuery();
//5、获取结果集
//数据表中的记录要复制到Java的Object中
//反射机制
//自动赋值
//拿到一共有多少个列
List<Object> result = new ArrayList<Object>();
int columnCount = rs.getMetaData().getColumnCount();
while (rs.next()){ //游标
//===========Begin ORM ============
Object instance = entityClass.newInstance();
for (int i = 1; i <= columnCount; i ++) {
String columnName = rs.getMetaData().getColumnName(i);
Field field = entityClass.getDeclaredField(columnName);
field.setAccessible(true);
//数据类型映射非常关键
// Object type = field.getType();
// if(type == Long.class){
// field.set(instance,rs.getLong(columnName));
// }else if(String.class == type){
// field.set(instance,rs.getString(columnName));
// }else if(Integer.class == type){
// field.set(instance,rs.getInt(columnName));
// }
field.set(instance,rs.getObject(columnName));
//各自的厂商实现自己的链接
//MySQL为例,以下类型Java语言中是不存在的
//bigint ,由开发厂商自动就映射好了
//varchar
//int
// System.out.println(rs.getObject(columnName).getClass());
}
//===========End ORM ==============
result.add(instance);
}
//System.out.println(Arrays.toString(result.toArray()));
//6、关闭结果集、关闭语句集、关闭连接
rs.close();
pstmt.close();
conn.close();
return result;
}catch(Exception e){
e.printStackTrace();
}finally {
//关闭资源要在Finally块中
}
return null;
}
}
import com.darian.spring.orm.demo.model.Member;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by Tom on 2018/5/9.
*/
public class JdbcTest {
public static void main(String[] args) {
// List<?> result = select(Member.class);
Member condition = new Member();
condition.setName("tom");
// condition.setAge(20);
List<?> result = select(condition);
System.out.println(Arrays.toString(result.toArray()));
}
//我框架问世的时候,你的Member类都还没有从石头缝里蹦出来
private static List<?> select(Object condition){
try{
Class<?> entityClass = condition.getClass();
//1、加载驱动类
Class.forName("com.mysql.jdbc.Driver");
//2、建立连接
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/gupaoedu_demo?characterEncoding=UTF-8&rewriteBatchedStatements=true","root","123456");
Table table = entityClass.getAnnotation(Table.class);
//3、创建语句开始事务
//为了简便,暂时用select * from 代替,不要说我不严谨,OK?
String sql = "select * from " + table.name();
StringBuffer where = new StringBuffer(" where 1=1 ");
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object value = field.get(condition);
if(null != value) {
Class<?> clazz = field.getType();
if(String.class == clazz){
where.append(" and " + field.getName() + " = '" + value + "'");
}else{
where.append(" and " + field.getName() + " = " + value);
}
}
}
System.out.println(sql + where.toString());
PreparedStatement pstmt = conn.prepareStatement(sql + where.toString());
//4、执行语句集
ResultSet rs = pstmt.executeQuery();
//5、获取结果集
//数据表中的记录要复制到Java的Object中
//反射机制
//自动赋值
//拿到一共有多少个列
List<Object> result = new ArrayList<Object>();
int columnCount = rs.getMetaData().getColumnCount();
while (rs.next()){ //游标
//===========Begin ORM ============
Object instance = entityClass.newInstance();
for (int i = 1; i <= columnCount; i ++) {
String columnName = rs.getMetaData().getColumnName(i);
Field field = entityClass.getDeclaredField(columnName);
field.setAccessible(true);
//数据类型映射非常关键
// Object type = field.getType();
// if(type == Long.class){
// field.set(instance,rs.getLong(columnName));
// }else if(String.class == type){
// field.set(instance,rs.getString(columnName));
// }else if(Integer.class == type){
// field.set(instance,rs.getInt(columnName));
// }
field.set(instance,rs.getObject(columnName));
//各自的厂商实现自己的链接
//MySQL为例,以下类型Java语言中是不存在的
//bigint ,由开发厂商自动就映射好了
//varchar
//int
// System.out.println(rs.getObject(columnName).getClass());
}
//===========End ORM ==============
result.add(instance);
}
//System.out.println(Arrays.toString(result.toArray()));
//6、关闭结果集、关闭语句集、关闭连接
rs.close();
pstmt.close();
conn.close();
return result;
}catch(Exception e){
e.printStackTrace();
}finally {
//关闭资源要在Finally块中
}
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113