背景
目前JAVA最常使用的ORM框架是Mybatis和JPA,很多项目中都会用到相关的,但一般项目在这两者中只能二选一,有些时候技术可能因为这个选型会起争执,对于这个我们不能全都要吗???要么我们就手搓一个简单的ORM,把两者的特点和功能都集成起来。但关这个题目相关的工作,看着好像工作量不少,不过作为工作了这么多年JAVA的技术,这个真的很难吗?
对于手搓轮子的一点感想
虽然人月和各种文章都告诉我们,不要重复造轮子,如果有适应各种情况的完美轮子的时候,我们确实没有必要自己模仿一个,但是各有优缺点需要对比选择的情况下,确实很多时候折衷是比较合适的一个方案;
从我自己的感受看,没有自己去造轮子,就难以理解造轮子的过程和需要的材料,用技术的角度来说,就是很多时候面试都问你看了这个诸如Spring的源码什么,我看了,但是很多时候我们都是一知半解,人云亦云,看了注释知道这段是啥功能,为啥要这么写,不能换其他的方式吗,这些我们很少去考虑,包括有些培训机构里面说的,大多是套话以及对技术点的说明,就是只说能用那些,怎么使用,有什么注意的一般不会讲。我觉得,真正理解是你自己思考后,尝试简单实现下,对于对技术的理解和今后的应用都是有好处的
方案技术点描述
1.兼容MybatisPlus的注解以及JPA的注解
MybatisPlus使用@TableName @TableId 等
JPA 使用 @Entity @Id 等
需通过注解的解析支持以上两种模式
2.主键的支持
支持 IDENTITY 自增
支持SEQUENCE序列
支持ASSIGN手工赋值
3.多主键支持
采用JPA的主键类型方式,未采用MybatisPlus的MppMultiId
4.查询配件
兼容Mybatis的查询配置xml文件
功能实现简要说明
具体实现参见我的框架工程 https://github.com/robinhood-jim/JavaFramework/tree/develop/core
自定义的实体注解
MappingEntity
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MappingEntity {
String value() default "";
String schema() default "";
String jdbcDao() default "jdbcDao";
//Does all field must declare explicit?
boolean explicit() default false;
}
自定义字段注解
MappingField
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MappingField {
String value() default "";
boolean primary() default false;
boolean increment() default false;
String sequenceName() default "";
boolean required() default false;
String datatype() default "";
int precise() default 0;
int scale() default 0;
int length() default 0;
boolean exclude() default false;
boolean keyword() default false;
}
数据访问层DAO实现接口
IJdbcDao
public interface IjdbcDao {
int queryByInt(String querySQL, Object... objects) throws DAOException;
Long queryByLong(String querySQL, Object... objects) throws DAOException;
......
}
数据访问Service层接口
IBaseAnnotationJdbcService
public interface IBaseAnnotationJdbcService<V extends BaseObject, P extends Serializable> {
P saveEntity(V vo) throws ServiceException;
int updateEntity(V vo) throws ServiceException;
int deleteEntity(P[] vo) throws ServiceException;
int deleteByField(String field, Object value) throws ServiceException;
int deleteByField(PropertyFunction<V,?> function, Object value) throws ServiceException;
V getEntity(P id) throws ServiceException;
void queryBySelectId(PageQuery<Map<String,Object>> query) throws ServiceException;
......
}