Spring Data JPA和Hibernate在大型项目中有何不同?

129

我很难决定是否应该在新项目中继续使用Hibernate,还是尝试使用JPA和新的Spring Data实现。

Spring Data框架是用于大型项目还是具有适度查询要求的小型项目?

虽然我确实看到了使用@Query注释减少代码量的优点,但是对于动态查询怎么办?当您想要实现相当复杂的save()方法时该怎么办?

文档中说要创建一个自定义接口和实现,然后使您的主存储库实现它,但如果需要访问crud仓库本身的任何超级方法怎么办?crud仓库实现了自定义仓库,而不是反过来。 这似乎是一种奇怪的设计。

我非常不确定这个框架是否能够应对复杂和大型应用程序的挑战。我从未遇到过Hibernate的太多问题,考虑是否坚持使用可靠的Hibernate而不是选择Spring Data JPA。

我该怎么办?如果我选择Spring Data JPA,会遇到哪些意想不到的问题和成本?


1
据我所知,这没有太大的区别。选择你更熟悉的那个吧。为什么要争论呢? - duffymo
1
我显然更喜欢使用Hibernate,但如果我能够做同样的事情并且更加高效,我宁愿采用更新的方法。然而,如果Hibernate仍然更强大,并且我会遇到更少的问题,那么这是我想知道的事情。 - egervari
3
JPA是ORM的一种泛化,使用Hibernate作为众多实现之一。 你认为其中一个比另一个更具优势是什么?JPA是一个标准,但我看不出它们之间有什么区别。为了全面披露,我想说我都不喜欢。两者都可以为你生成SQL,但ORM并非适用于每个问题和每个用户。 - duffymo
1
我同意。就JPA或Hibernate而言,我每次都会选择Hibernate。我真的不太喜欢JPA本身的实现。IDEA中的支持实际上还是有点糟糕的,如果映射不正确,它会在应用程序启动时发出警告而不是让单元测试运行。我对JPA还有很多其他吹毛求疵的地方。我实际上有点喜欢旧的Hibernate XML映射文件。这样做的好处是可以使我的对象看起来更加简洁。Spring Data JPA提供了许多新功能,所以我最近一直在思考是否值得切换。 - egervari
3
“Spring Data”不是JPA的一个实现或其他什么东西。它只是采用一个现有的JPA实现,并简化您提供给它的内容。 JPA实现仍然在底层执行所有工作。 - Neil Stockton
显示剩余2条评论
3个回答

107

所以,spring-data 进行了一些额外的魔法,有助于处理复杂的查询。一开始会觉得很奇怪,在文档中你可能完全跳过它,但它确实非常强大和有用。

它涉及创建自定义的 Repository 和自定义的 `RepositoryImpl',并告诉 Spring 去哪里找它。这是一个例子:

配置类 - 使用注释指向您的存储库包(现在会自动查找 *Impl 类),指向您仍需的 xml 配置:

@Configuration
@EnableJpaRepositories(basePackages = {"com.examples.repositories"})
@EnableTransactionManagement
public class MyConfiguration {
}

jpa-repositories.xml - 告诉Spring在哪里找到你的repositories,同时告诉Spring查找文件名为CustomImpl的自定义repositories:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<jpa:repositories base-package="com.example.repositories" repository-impl-postfix="CustomImpl" />

</beans>

MyObjectRepository - 这是您可以放置带注释和未注释的查询方法的位置。请注意此存储库接口如何扩展Custom

@Transactional
public interface MyObjectRepository extends JpaRepository<MyObject, Integer>, MyObjectRepositoryCustom {

    List<MyObject> findByName(String name);

    @Query("select * from my_object where name = ?0 or middle_name = ?0")
    List<MyObject> findByFirstNameOrMiddleName(String name);
}

MyObjectRepositoryCustom - 存储库方法更加复杂,无法通过简单查询或注解来处理:

public interface MyObjectRepositoryCustom {

    List<MyObject> findByNameWithWeirdOrdering(String name);
}

MyObjectRepositoryCustomImpl - 在此处使用自动注入的EntityManager实现这些方法:

public class MyObjectRepositoryCustomImpl implements MyObjectRepositoryCustom {

    @Autowired
    private EntityManager entityManager;

    public final List<MyObject> findByNameWithWeirdOrdering(String name) {
        Query query = query(where("name").is(name));
        query.sort().on("whatever", Order.ASC);
        return entityManager.find(query, MyObject.class);
    }
}

令人惊讶的是,当你执行以下操作时,这一切都会汇聚在一起,来自两个接口(以及你实现的CRUD接口)的方法都会显示出来:

myObjectRepository.
你会看到:
myObjectRepository.save()
myObjectRepository.findAll()
myObjectRepository.findByName()
myObjectRepository.findByFirstNameOrMiddleName()
myObjectRepository.findByNameWithWeirdOrdering()

它确实可以工作。您只需要一个接口来查询数据。spring-data已经准备好应对大型应用程序了。并且您能将尽可能多的查询封装成简单的方法或者注解,这样会更加优秀。

所有这些都在Spring Data Jpa网站上有记录。


5
这实际上是我尝试过的方法,并且在某种程度上它是有效的。我的问题是,如果你想覆盖save()方法怎么办?例如,假设你正在保存一篇博客,并且你想在save()方法中处理/保存与它相关联的标签,因为把它放在一个服务中没有最好的意义。这在原始的Hibernate中很容易实现,但是我没有找到使用Spring JPA的好方法。虽然你的答案是正确的,我会将它标记为正确的。这基本上就是Spring Data JPA可以做的事情。不过我想我还是会坚持使用Hibernate。这个答案肯定会帮助其他人。 - egervari
8
你可以实现自己的JpaRepository -> MyJpaRepository。你还需要创建一个MyJpaRepositoryFactoryBean,但是如果你正确设置了所有内容,你可以重写.save()方法。这里是Spring Data JPA文档:http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/#repositories.custom-behaviour-for-all-repositories 不要轻易放弃! - sbzoom
@Picrochole,您如何解释“应用程序的较低层”?调用DAO的服务是否属于较低层? - Rumid

12

我在一些简单查询需求的小型和大型项目中使用了Spring Data JPA。其主要优势是甚至不需要使用@Query注释就可以完成查询。在Spring Data中没有任何阻止您将其用于大型项目的内容,而最近添加的QueryDSL支持可能会对您有所帮助。这是一个示例,使用QueryDSL来定位Hibernate。

如果您预见到复杂的查询,并且您感到舒适使用基于Hibernate的对象而不使用JPA,则我认为替代组合可以是在简单的Spring Data Repository旁边放置具有您可能需要的特定方法的复杂Hibernate-based仓库。这可能比将Hibernate实现扭曲成Spring Data JPA结构更少的烦恼。


2
我觉得在同一个项目中混用不同的api查询不如使用相同一致的api。我仍然没有找到针对复杂Spring Data JPA问题的好解决方案,并且由于我一般对JPA有很多小问题,所以我认为我可能会更愿意接受Hibernate作为我的ORM。我将有很多复杂的查询,而我无法承担40/60的混合。这对我来说不值得 :( - egervari
1
您也可以直接使用Querydsl而不需要Spring Data,这将为您提供一个强大的查询层,位于JPA之上。 - Timo Westkämper

5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接