技术专题讨论:如何对 JPA 或者 MyBatis 进行技术选型

在咱们平时的项目中,你们都知道可使用 JPA 或者 Mybatis 做为 ORM 层。对 JPA 和 Mybatis 如何进行技术选型?git

下面看看大精华总结以下:github

最佳回答

首先表达我的观点,JPA必然是首选的。redis

我的认为仅仅讨论二者使用起来有何区别,何者更加方便,不足以真正的比较这两个框架。要评判出更加优秀的方案,我以为能够从软件设计的角度来评判。我的对 mybatis 并不熟悉,但 JPA 规范和 springdata 的实现,设计理念绝对是超前的。软件开发复杂性的一个解决手段是遵循 DDD(DDD 只是一种手段,但不是惟一手段),而我着重几点来聊聊 JPA 的设计中是如何体现领域驱动设计思想的,抛砖引玉。spring

聚合根和值对象

领域驱动设计中有两个广为你们熟知的概念,entity(实体)和 value object(值对象)。entity 的特色是具备生命周期的,有标识的,而值对象是起到一个修饰的做用,其具备不可变性,无标识。在 JPA中 ,须要为数据库的实体类添加 @Entity 注解,相信你们也注意到了,这并非巧合。sql

@Entity
@Table(name = "t_order")
public class Order {
    @Id
    private String oid;

    @Embedded
    private CustomerVo customer;
    @OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "order")
    private List<OrderItem> orderItems;
}

如上述的代码,Order 即是 DDD 中的实体,而 CustomerVo,OrderItem 则是值对象。程序设计者无需关心数据库如何映射这些字段,由于在 DDD 中,须要作的工做是领域建模,而不是数据建模。实体和值对象的意义不在此展开讨论,但经过此能够初见端倪,JPA 的内涵毫不仅仅是一个 ORM 框架。mongodb

仓储

Repository 模式是领域驱动设计中另外一个经典的模式。在早期,咱们经常将数据访问层命名为:DAO,而在 SpringData JPA 中,其称之为 Repository(仓储),这也不是巧合,而是设计者有意为之。数据库

熟悉 SpringData JPA 的朋友都知道当一个接口继承 JpaRepository 接口以后便自动具有了 一系列经常使用的数据操做方法,findAll, findOne ,save等。缓存

public interface OrderRepository extends JpaRepository<Order, String>{
}

那么仓储和DAO到底有什么区别呢?这就要提到一些遗留问题,以及一些软件设计方面的因素。在此次SpringForAll 的议题中我可以预想到有不少会强调 SpringData JPA 具备方即可扩展的 API,像下面这样:mybatis

public interface OrderRepository extends JpaRepository<Order, String>{

      findByOrderNoAndXxxx(String orderNo,Xxx xx);

    @Transactional
    @Modifying(clearAutomatically = true)
    @Query("update t_order set order_status =?1 where id=?2")
    int updateOrderStatusById(String orderStatus, String id);
}

但我要强调的是,这是 SpringData JPA 的妥协,其支持这一特性,并不表明其建议使用。由于这并不符合领域驱动设计的理念。注意对比,SpringData JPA 的设计理念是将 Repository 做为数据仓库,而不是一系列数据库脚本的集合,findByOrderNoAndXxxx 方法能够由下面一节要提到的JpaSpecificationExecutor代替,而 updateOrderStatusById 方法则能够由 findOne + save 代替,不要以为这变得复杂了,试想一下真正的业务场景,修改操做通常不会只涉及一个字段的修改, findOne + save 能够帮助你完成更加复杂业务操做,而没必要关心咱们该如何编写 SQL 语句,真正作到了面向领域开发,而不是面向数据库 SQL 开发,面向对象的拥趸者也必然会以为,这更加的 OO。架构

Specification

上面提到 SpringData JPA 能够借助 Specification 模式代替复杂的 findByOrderNoAndXxxx 一类 SQL 脚本的查询。试想一下,业务不停在变,你怎么知道未来的查询会不会多一个条件 变成 findByOrderNoAndXxxxAndXxxxAndXxxx.... 。SpringData JPA 为了实现领域驱动设计中的 Specification 模式,提供了一些列的 Specification 接口,其中最经常使用的即是 :JpaSpecificationExecutor

public interface OrderRepository extends JpaRepository<Order,String>,JpaSpecificationExecutor<Order>{
}

使用 SpringData JPA 构建复杂查询(join操做,汇集操做等等)都是依赖于 JpaSpecificationExecutor 构建的 Specification 。例子就不介绍,有点长。

请注意,上述代码并非一个例子,在真正遵循 DDD 设计规范的系统中,OrderRepository 接口中就应该是干干净净的,没有任何代码,只须要继承 JpaRepository (负责基础CRUD)以及 JpaSpecificationExecutor (负责Specification 查询)便可。固然, SpringData JPA 也提供了其余一系列的接口,根据特定业务场景继承便可。

乐观锁

为了解决数据并发问题,JPA 中提供了 @Version ,通常在 Entity 中 添加一个 Long version 字段,配合 @Version 注解,SpringData JPA 也考虑到了这一点。这一点侧面体现出,JPA 设计的理念和 SpringData 做为一个工程解决方案的双剑合璧,造就出了一个伟大的设计方案。

复杂的多表查询

不少人青睐 Mybatis ,缘由是其提供了便利的 SQL 操做,自由度高,封装性好……SpringData JPA对复杂 SQL 的支持很差,没有实体关联的两个表要作 join ,的确要花很多功夫。但 SpringData JPA 并不把这个当作一个问题。为何?由于现代微服务的架构,各个服务之间的数据库是隔离的,跨越不少张表的 join 操做本就不该该交给单一的业务数据库去完成。解决方案是:使用 elasticSearch作视图查询 或者 mongodb 一类的Nosql 去完成。问题本不是问题。

总结

真正走进 JPA,真正走进 SpringData 会发现,咱们并非在解决一个数据库查询问题,并非在使用一个 ORM 框架,而是真正地在实践领域驱动设计。

(再次补充:DDD 只是一种手段,但不是惟一手段)

第二名回答

lexburne 兄说的也很不错了,不过我还想在补充2点,来消除你们对使用spring data jpa 的误解
spring data jpa 的好处我相信你们都了解,就是开发速度很快,很方便,你们不肯意使用spring data jpa 的地方一般是由于sql 不是本身写的,不可控,复杂查询很差搞,那么下面我要说的就是其实对于这种需求,spring data jpa 是彻底支持的!!

  1. 第一种方式:@query 注解指定nativeQuery,这样就可使用原生sql查询了,示例代码来自官方文档:

    public interface UserRepository extends JpaRepository<User, Long> {
    
    @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
    User findByEmailAddress(String emailAddress);
    }

    2.若是单靠sql搞不定怎么办?必需要写逻辑怎么办?可使用官方文档3.6.1 节:Customizing individual repositories 提供的功能去实现,先看官方文档的代码:

    interface CustomizedUserRepository {
    void someCustomMethod(User user);
    }
    class CustomizedUserRepositoryImpl implements CustomizedUserRepository {
    
    public void someCustomMethod(User user) {
     // Your custom implementation
    }
    }
    interface UserRepository extends CrudRepository<User, Long>, CustomizedUserRepository {
    
    // Declare query methods here
    }

    我来解释下上面的代码,若是搞不定的查询方法,能够自定义接口,例如CustomizedUserRepository ,和他的实现了类,而后在这个实现类里用你本身喜欢的dao 框架,好比说mybatis ,jdbcTemplate ,都随意,最后在用UserRepository 去继承CustomizedUserRepository接口,就实现了和其余dao 框架的组合使用!!

那么下面我在总结1下,有了上面介绍的2种功能,你还在担忧,使用spring data jpa 会有局限么,他只会加速你的开发速度,并容许你组合使用其余框架,只有好处,没有坏处。。
最后再说1点,我最近在看es ,而后看了下spring data es 的文档,大概扫了1下,我发现,学会spring data 其中某1个系列之后,在看其余的,我发现我都不用花时间学。。直接就能够用,对就是这么神奇~~

第三

工做以来一直是使用 hibernate 和 mybatis,总结下来通常传统公司、我的开发(可能只是我)喜欢用jpa,互联网公司更青睐于 mybatis
缘由:,而mybatis 更加灵活。开发迭代模式决定的,传统公司需求迭代速度慢,项目改动小,hibernate能够帮他们作到一劳永逸;而互联网公司追求快速迭代,需求快速变动,灵活的 mybatis 修改起来更加方便,并且通常每一次的改动不会带来性能上的降低,hibernate常常由于添加关联关系或者开发者不了解优化致使项目愈来愈糟糕(原本开始也是性能很好的)

一、mybatis官方文档就说了他是一个半自动化的持久层框架,相对于全自动化的 hibernate 他更加的灵活、可控
二、mybatis 的学习成本低于 hibernate。hibernate 使用须要对他有深刻的理解,尤为是缓存方面,做为一个持久层框架,性能依然是第一位的。

hibernate 它有着三级缓存,一级缓存是默认开启的,二级缓存须要手动开启以及配置优化,三级缓存能够整合业界流行的缓存技术 redis,ecache 等等一块儿去实现
hibernate 使用中的优化点:
一、缓存的优化
二、关联查询的懒加载(在开发中,仍是不建议过多使用外键去关联操做)

jpa(Java Persistence API) 与 hibernate 的关系:
Jpa是一种规范,hibernate 也是听从他的规范的。
springDataJpa 是对 repository 的封装,简化了 repository 的操做

第四

  • 数据分析型的OLAP应用适合用MyBatis,事务处理型OLTP应用适合用JPA。
  • 越是复杂的业务,越须要领域建模,建模用JPA实现最方便灵活。可是JPA想用好,门槛比较高,不懂DDD的话,就会沦为增删改查了。
  • 复杂的查询应该是经过CQRS模式,经过异步队列创建合适查询的视图,经过视图避免复杂的Join,而不是直接查询领域模型。
  • 从目前的趋势来看OLAP交给NoSQL数据库可能更合适

第五

使用了一段时间jpa,而mybatis是以前一直在用的,不说区别是啥,由于有不少人比较这两个框架了!
从国内开源的应用框架来看,国内使用jpa作orm的人仍是比较少,若是换成hibernate还会多一些,因此面临的风险可能就是你会用,和你合做的人不必定会用,若是要多方协做,确定要考虑这个问题!
灵活性方面,jpa更灵活,包括基本的增删改查、数据关系以及数据库的切换上都比mybatis灵活,可是jpa门槛较高,另外就是更新数据须要先将数据查出来才能进行更新,数据量大的时候,jpa效率会低一些,这时候须要作一些额外的工做去处理!
如今结合Springboot有Springdata jpa给到,不少东西都简化了,感兴趣而且有能力能够考虑在公司内部和圈子里推广!个人博客里有一些简单使用jpa的示例,https://github.com/icnws/spring-data-jpa-demo

第六

1.相对来讲,jpa的学习成本比mybatis略高 2.公司业务需求频繁变动致使表结构复杂,此处使用mybatis比jpa更灵活 3.就方言来说,通常公司选定数据库后再变动微乎其微,因此此处方言的优点能够忽略

相关文章
相关标签/搜索