江苏南大先腾J2EE持久化框架(三)用jdbc对JPA进行实现和扩展[附源码]

动机

主流的Orm框架有Hibernate、Mybatis和Spring Data。以往我一直推荐使用Hibernate,使用jpa注解不需要写sql语句也不要配置文件,确实比较便捷。说hibernate效率低下,主要式指用hibernate进行查询和统计,我觉得这是不公平的,查询可以原生sql直接返回jsonarry来做,没有必要用hibernate的orm模型做。hibernate功能确实强大,换一个方式来说也就是很难娴熟的掌握,光是对象的三种状态就把一半人搞晕。所以现在我也不推荐大家使用了,没有必要在持久化层花费太多尽力学习。MyBatis现在用的人越来越多,但是比较烦它的配置文件越来越讨厌xml格式的配置文件。Spring Data接触的较少;但是到时有很多人用spring jdbc。先腾框架持久化模块中有三个自摸库分别对Hibernate、Mybatis和spring jdbc进行了封装,让开发人员可以选择不同的技术,但使用的接口有尽量统一。

这篇博文主要将用jdbc实现jpa,这个作用就是将使用jdbc的方式和hibernate一样,jpa的标准就是jboss提供的。工程源码。先腾的Orm只实现了数据库增删改查的基本操作,没有实现缓存之类的额外特性。是JPA的一个最常用的子集,在系统开发的实践中验证过能够满足一般业务系统的开发需求。

jpa注解扩展

JPA注解已经很全,但是一些细节不太满意,对其进行了扩展。

Lazy 懒加载

JPA的关联注解(OneToMany、ManyToOne)中FetchType有lazy懒加载的选项。Lob字段的默认也是懒加载的,但是感觉并不是直观。 所以添加了一个Lazy注解,用于字段Column属性,明确的标注这个字段为懒加载,而不考虑这个字段是否式lob字段,任何类型都可以懒加载。
另外,所以的关联关系都是默认懒加载的,并且无法修改这个默认属性,如果需要同步加载,在调用方法中需要明确说明,这样避免没有必要的性能消耗。

ValueGenerator 值生成器

JPA 有一个注解GeneratedValue 这个式用于主键的,并且不够灵活,所以定义了一个ValueGenerator注解,这个注解并不要一定用在主键上,任何字段都可以,可以把它作为insert 或者 update 的前置触发器。

@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ValueGenerator {
    /**
     * 数值生成方式 
     *   Auto 数据库自动增长、 SEQUENCE 序列 value中保存序列名称 、
     *   UUID 、 CONSTANT 常量 value中保存常量、
     *   FUNCTION 公式 value中保存公式,是一个四则运算表达式,可以通过变量引用这个对象的其他属性
     * @return GeneratorType
     */
    GeneratorType strategy() default GeneratorType.AUTO;
    /**
     * 数值生成时机 NEW (insert) UPDATE (update) READ (select)
     * @return GeneratorTime
     */
    GeneratorTime occasion() default GeneratorTime.NEW;
    /**
     * 生成条件 IFNULL 数值为空时生成 ALWAYS 总是生成,会覆盖已有的值
     * @return GeneratorCondition
     */
    GeneratorCondition condition() default GeneratorCondition.IFNULL;
    /**
     * 具体生成参数 对应 GeneratorType 不同有不用的意思
     * @return
     */
    String value() default "";
}

需要特别说明的式strategy = GeneratorType.FUNCTION 非常灵活可以通过对象的其他属性计算得出这个字段的值,这时value中的值为四则运算表达式。使用示例:

/**
     * UPDATEDATE(更新时间) 更新时间
     */
    @Column(name = "UPDATE_DATE")
    @ValueGenerator( strategy= GeneratorType.FUNCTION, value = "today()", 
		    condition = GeneratorCondition.ALWAYS, occasion = GeneratorTime.ALWAYS )
    private Date  updateDate;

这个注解的意思就是只要这个对象有更新,updateDate字段就更新为当前日期,代码中无需对这个字段赋值。

元数据 JpaMetadata

JpaMetadata 中维护了类和数据库表结构的对应关系,在第一次使用到这个类的时候收集类上的注解信息,并将其保存在JpaMetadata中。每次访问数据库就是根据这个元数据来生成sql语句。框架中 JsonObjectDao 类实现了不同数据库之间的方言,这个不是本文的重点,有兴趣的可以看一下,欢迎给出宝贵建议。

JPA的增删改查具体实现 OrmDaoUtils

OrmDaoUtils 中所有的方法都需要传递一个connection 数据库连接参数。其中的方法分以下几类:

get*

getObject* 就是获取一个对象的查询。

list*

listObjects* 就是更加属性查询一组对象,可以分页查询。

query*

queryObjects* 是更加sql语句查询,这个相对更加灵活,可以分页查询。

save*

save* Object * 保存新对象。

update*

updateObject 更改对象。

merge*

mergeObject 合并对象,可以理解为insert Or Update。

* Cascade *

方法名中有Cascade单词的,表示会级联查询,就是会根据OneToMany、OneToOne等等关联关系查询关联表。

fetch*

fetch* 方法为获取Lazy对应的字段。

持久化框架考虑

先腾框架持久化模块中spring jdbc模块中,对这写方法进行了再次封装,将JdbcTemplate中的数据库链接传递给OrmDaoUtils,这样就不需要connection这个参数了,参见BaseDaoImpl源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值