Oleg Atamanenko
Очевидно, что мы не всегда можем воспользоваться автоматической генерацией кода, предоставляемой Spring Data JPA. Например, у нас слишком сложный запрос, или нам необходимо вызвать процедуру в базе данных, либо у нас сложная бизнес-логика.
Рассмотрим следующий пример - например, нам нужна функциональность уникального счётчика, который мы решили реализовать с помощью последовательности (sequence).
Сначала определим интерфейс, в котором опишем все методы, которые мы будем реализовывать самостоятельно. В нашем случае, это будет только один метод:
public interface UserRepositoryCustom {
/**
* Returns next unique id.
*
* @return next unique id.
*/
Integer getNextUniqueId();
}
Затем обновим объявление репозитория, чтобы он унаследовал новый интерфейс UserRepositoryCustom
public interface UserRepository extends JpaRepository<User, Integer>, UserRepositoryCustom {
...
}
Теперь напишем реализацию метода:
public class UserRepositoryImpl implements UserRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
@Override
public Integer getNextUniqueId() {
// When using Hibernate via JPA native queries fails with mapping exception, so just use Hibernate directly:
Session session = (Session) entityManager.getDelegate();
SQLQuery nativeQuery = session.createSQLQuery("SELECT \"nextval\"('unique_id_seq') ");
List<BigInteger> list = nativeQuery.list();
if (list.isEmpty()) {
throw new IncorrectResultSizeDataAccessException(1);
}
BigInteger result = list.get(0);
return result.intValue();
}
}
И, наконец, укажем Spring Data JPA, чтобы в качестве класса для прокси использовался наш класс с реализацией собственных методов. Для этого нам нужна ещё одна секция repositories в конфигурационном файле:
<repositories base-package="[base.repository.package]"/>
<repositories base-package="[base.repository.package]">
<repository id="userRepository" custom-impl-ref="userRepositoryImpl"/>
</repositories>
<beans:bean id="userRepositoryImpl" class="...UserRepositoryImpl"/>
Вот и всё.