如何将自定义方法添加到Spring Data JPA

我正在研究Spring Data JPA。 考虑下面的例子,我将默认使用所有的crud和finderfunction,如果我想定制一个finder,那么在界面本身也可以轻松完成。

@Transactional(readOnly = true) public interface AccountRepository extends JpaRepository<Account, Long> { @Query("<JPQ statement here>") List<Account> findByCustomer(Customer customer); } 

我想知道如何添加一个完整的自定义方法与上述AccountRepository的实现? 由于它的接口,我不能在那里实现的方法。

您需要为自定义方法创build一个单独的界面:

 public interface AccountRepository extends JpaRepository<Account, Long>, AccountRepositoryCustom { ... } public interface AccountRepositoryCustom { public void customMethod(); } 

并为该接口提供一个实现类:

 public class AccountRepositoryImpl implements AccountRepositoryCustom { @Autowired AccountRepository accountRepository; /* Optional - if you need it */ public void customMethod() { ... } } 

也可以看看:

  • 1.3.1。 将行为添加到单个存储库

除了axtavt的回答 ,不要忘了你可以注入实体pipe理器在你的自定义实现,如果你需要它来build立你的查询:

 public class AccountRepositoryImpl implements AccountRepositoryCustom { @PersistenceContext private EntityManager em; public void customMethod() { ... em.createQuery(yourCriteria); ... } } 

我使用下面的代码,以便从我的自定义实现访问生成的查找方法。 通过bean工厂获得实现可以防止循环bean的创build问题。

 public class MyRepositoryImpl implements MyRepositoryExtensions, BeanFactoryAware { private BrandRepository myRepository; public MyBean findOne(int first, int second) { return myRepository.findOne(new Id(first, second)); } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { myRepository = beanFactory.getBean(MyRepository.class); } } 

这在使用上有限,但对于简单的自定义方法,您可以使用默认的接口方法,如:

 import demo.database.Customer; import org.springframework.data.repository.CrudRepository; public interface CustomerService extends CrudRepository<Customer, Long> { default void addSomeCustomers() { Customer[] customers = { new Customer("Józef", "Nowak", "nowakJ@o2.pl", 679856885, "Rzeszów", "Podkarpackie", "35-061", "Zamknięta 12"), new Customer("Adrian", "Mularczyk", "adii333@wp.pl", 867569344, "Krosno", "Podkarpackie", "32-442", "Hynka 3/16"), new Customer("Kazimierz", "Dejna", "sobieski22@weebly.com", 996435876, "Jarosław", "Podkarpackie", "25-122", "Korotyńskiego 11"), new Customer("Celina", "Dykiel", "celina.dykiel39@yahoo.org", 947845734, "Żywiec", "Śląskie", "54-333", "Polna 29") }; for (Customer customer : customers) { save(customer); } } } 

编辑:

在今年spring的教程中写道:

Spring Data JPA还允许您通过简单地声明其方法签名来定义其他查询方法。

所以甚至可以像这样声明方法:

 Customer findByHobby(Hobby personHobby); 

如果对象Hobby是客户的一个属性,那么Spring将自动为你定义方法。

如果你想能够做更复杂的操作,你可能需要访问Spring Data的内部,在这种情况下,以下工作(作为我对DATAJPA-422的临时解决scheme):

 public class AccountRepositoryImpl implements AccountRepositoryCustom { @PersistenceContext private EntityManager entityManager; private JpaEntityInformation<Account, ?> entityInformation; @PostConstruct public void postConstruct() { this.entityInformation = JpaEntityInformationSupport.getMetadata(Account.class, entityManager); } @Override @Transactional public Account saveWithReferenceToOrganisation(Account entity, long referralId) { entity.setOrganisation(entityManager.getReference(Organisation.class, organisationId)); return save(entity); } private Account save(Account entity) { // save in same way as SimpleJpaRepository if (entityInformation.isNew(entity)) { entityManager.persist(entity); return entity; } else { return entityManager.merge(entity); } } } 

考虑到你的代码片段,请注意,你只能将Native对象传递给findBy ###方法,假设你想加载属于某个客户端的账户列表,一个解决scheme就是这样做,

  @Query("Select a from Account a where a."#nameoffield"=?1") List<Account> findByCustomer(String "#nameoffield"); 

使起诉表的名称被查询是相同的实体类。 进一步的实现请看看这个

这里还有一个问题需要考虑。 有些人希望将自定义方法添加到存储库中会自动在“/ search”链接下将它们公开为REST服务。 这不幸的是不是这种情况。 Spring目前不支持。

这是“按devise”特征,spring数据rest明确地检查方法是否是自定义方法,并且不会将其公开为RESTsearch链接:

 private boolean isQueryMethodCandidate(Method method) { return isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method); } 

这是奥利弗·吉尔克的一个口号:

这是devise。 自定义存储库方法没有查询方法,因为它们可以有效地实现任何行为 因此,我们现在不可能决定HTTP方法来揭示这个方法。 POST将是最安全的select,但这不符合通用查询方法(接收GET)。

有关更多详细信息,请参阅此问题: https : //jira.spring.io/browse/DATAREST-206