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 例子
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;
}
}
微信公众号:不止极客