(스프링 데이터 JPA 사용하기) 두 엔티티 Parent
& Child
과 OneToMany/ManyToOne 양방향 관계가있다. 내가 그렇게 같은 부모 개체에 @NamedEntityGraph
을 추가하여 부모의 자녀에 대한 유형을 가져스프링 데이터 JPA + JpaSpecificationExecutor + EntityGraph
@Entity
@NamedEntityGraph(name = "Parent.Offspring", attributeNodes = @NamedAttributeNodes("children"))
public class Parent{
//blah blah blah
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
Set<Child> children;
//blah blah blah
}
주의하는 것이 LAZY이다. 이것은 의도적입니다. 개별 부모에게 질의 할 때 항상 아이들에게 열심히로드하고 싶지는 않습니다. 일반적으로 나는 네임드 엔티티 그래프를 사용하여 필요할 때 아이들을 열정적으로로드 할 수 있습니다. 하지만 .....
하나 이상의 부모를 쿼리하고 자녀를 열심히로드하려는 특정 상황이 있습니다. 이 외에도 프로그래밍 방식으로이 쿼리를 작성할 수 있어야합니다. 스프링 데이터는 동적 쿼리를 만들 수있는 JpaSpecificationExecutor을 제공하지만,이 특정 경우에는 열정적으로로드하는 자식을 위해 엔티티 그래프와 함께 사용하는 방법을 알 수 없습니다. 이것은 가능한가? 사양을 사용하는 많은 엔티티에 열의를 보내는 다른 방법이 있습니까?
@NoRepositoryBean
public interface CustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
List<T> findAll(Specification<T> spec, EntityGraphType entityGraphType, String entityGraphName);
Page<T> findAll(Specification<T> spec, Pageable pageable, EntityGraphType entityGraphType, String entityGraphName);
List<T> findAll(Specification<T> spec, Sort sort, EntityGraphType entityGraphType, String entityGraphName);
T findOne(Specification<T> spec, EntityGraphType entityGraphType, String entityGraphName);
}:
는 또한 구현 만들 :
@NoRepositoryBean
public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements CustomRepository<T, ID> {
private EntityManager em;
public CustomRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.em = em;
}
@Override
public List<T> findAll(Specification<T> spec, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
TypedQuery<T> query = getQuery(spec, (Sort) null);
query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
return query.getResultList();
}
@Override
public Page<T> findAll(Specification<T> spec, Pageable pageable, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
TypedQuery<T> query = getQuery(spec, pageable.getSort());
query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
return readPage(query, pageable, spec);
}
@Override
public List<T> findAll(Specification<T> spec, Sort sort, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
TypedQuery<T> query = getQuery(spec, sort);
query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
return query.getResultList();
}
@Override
public T findOne(Specification<T> spec, EntityGraph.EntityGraphType entityGraphType, String entityGraphName) {
TypedQuery<T> query = getQuery(spec, (Sort) null);
query.setHint(entityGraphType.getKey(), em.getEntityGraph(entityGraphName));
return query.getSingleResult();
}
}
을 그리고 공장 만들 :
public class CustomRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new CustomRepositoryFactory(entityManager);
}
private static class CustomRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {
private EntityManager entityManager;
public CustomRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new CustomRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
//to check for QueryDslJpaRepository's which is out of scope.
return CustomRepository.class;
}
}
}
을 그리고
혹시이 질문에 대한 답을 찾으셨습니까 설정 repositoryFactoryBeanClass를 만들 필요가 없습니다? – Joep
불행히도, 아니요. – Kerby