Ответ 1
Мы столкнулись с подобной проблемой и разработали несколько перспективных решений, но, похоже, нет изящного решения для того, что кажется общей проблемой.
1) Префиксы. Данные jpa предоставляют несколько префиксов (find, get,...) для имени метода. Одна из возможностей - использовать разные префиксы с разными именованными графами. Это наименьшая работа, но скрывает смысл метода от разработчика и имеет большой потенциал, чтобы вызвать некоторые неочевидные проблемы с загрузкой неправильных объектов.
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
@EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
User findByUserID(int id);
@EntityGraph(value = "User.membershipYears", type = EntityGraphType.LOAD)
User readByUserId(int id);
}
2) CustomRepository. Другими возможными решениями являются создание настраиваемых методов запросов и внедрение EntityManager. Это решение дает вам самый чистый интерфейс для вашего репозитория, потому что вы можете назвать свои методы чем-то значимым, но значительная сложность добавить к вашему коду для предоставления решения. И вы вручную захватываете диспетчер объектов вместо использования Spring магия.
interface UserRepositoryCustom {
public User findUserWithMembershipYearsById(int id);
}
class UserRepositoryImpl implements UserRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public User findUserWithMembershipYearsById(int id) {
User result = null;
List<User> users = em.createQuery("SELECT u FROM users AS u WHERE u.id = :id", User.class)
.setParameter("id", id)
.setHint("javax.persistence.fetchgraph", em.getEntityGraph("User.membershipYears"))
.getResultList();
if(users.size() >= 0) {
result = users.get(0);
}
return result;
}
}
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
@EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
User findByUserID(int id);
}
3) JPQL. По сути, это просто отказ от названных графиков объектов и использование JPQL для обработки ваших соединений для вас. Не идеальный, по моему мнению.
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
@EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
User findByUserID(int id);
@Query("SELECT u FROM users WHERE u.id=:id JOIN??????????????????????????")
User findUserWithTags(@Param("id") final int id);
}
Мы пошли с вариантом 1, потому что это самый простой в реализации, но это означает, что когда мы используем наши репозитории, нам приходится искать методы извлечения, чтобы убедиться, что мы используем тот, у которого есть правильный граф сущности. Удачи.
Источники:
- JPA EntityGraph с различными представлениями с помощью Spring
- https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods
У меня недостаточно репутации, чтобы публиковать все мои источники. Извините: (