Spring数据JPA,在CrudRepository接口中参数化@EntityGraph
Spring Data JPA, parametrize @EntityGraph in CrudRepository interface
是否可以使用 Spring Data JPA 来做 smth。像这样:
public interface UserDao extends CrudRepository<User, Long> {
@EntityGraph(value = :graphName, type = EntityGraph.EntityGraphType.LOAD)
@Query(value = "SELECT DISTINCT u FROM User u")
List<User> findAllWithDetailsByGraphName(@Param(value="graphName") String graphName);
}
能够在 运行 时将 graphName 传递到方法中并使用一组需要的集合调用负载?此构造不起作用,产生编译时错误。任何围绕它的游戏也失败了...
因此,我在用户 class 中有多个集合,我想根据条件加载这些集合;
@Entity
@Table(name="user")
@NamedEntityGraphs({
@NamedEntityGraph(name = "User.details", attributeNodes = {
@NamedAttributeNode("phones"), @NamedAttributeNode("emails"), @NamedAttributeNode("pets")}),
@NamedEntityGraph(name = "User.phones", attributeNodes =
{@NamedAttributeNode("phones")}),
@NamedEntityGraph(name = "User.emails", attributeNodes =
{@NamedAttributeNode("emails")}),
@NamedEntityGraph(name = "User.pets", attributeNodes =
{@NamedAttributeNode("pets")})
})
public class User {
@Id
@GeneratedValue(strategy= GenerationType.AUTO, generator="native")
@GenericGenerator(name = "native", strategy = "native")
@Column(name="user_id")
private Long userId;
@Column(name="name")
private String name;
// more fields omitted
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Phone> phones;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Email> emails;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Pet> pets;
}
现在,我只需隐式声明所有方法,如下所示:
@EntityGraph(value = "User.phones", type = EntityGraph.EntityGraphType.LOAD)
@Query(value = "SELECT DISTINCT u FROM User u")
List<User> findAllWithPhones();
谢谢你的建议!
您可以定义一个接受实体图作为参数的基本 JPA 存储库。这在与 Specification
s 结合时特别有用。因此,下面是一个基于 Specification
s 的例子。也可以使用不同类型的参数构造其他查询。
@NoRepositoryBean
public interface MyBaseRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
T findOne(Specification<T> spec, EntityGraphType entityGraphType, String entityGraphName);
List<T> findAll(Specification<T> spec, Sort sort, EntityGraphType entityGraphType, String entityGraphName);
}
实施基本存储库:
@NoRepositoryBean
public class MyBaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyBaseRepository<T, ID> {
private EntityManager em;
public MyBaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.em = entityManager;
}
public MyBaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.em = em;
}
@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();
}
@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();
}
}
指定自定义基础存储库:
<jpa:repositories base-package="my.domain" base-class="my.repository.MyBaseRepositoryImpl" />
从自定义基础存储库扩展:
public interface UserRepository extends JpaRepository<User, Long>, MyBaseRepository<User, Long>, JpaSpecificationExecutor<User> {
}
使用自定义存储库的方法:
Specification mySpecs = ...
List<User> user = picklistRepository.findAll(mySpecs, EntityGraphType.LOAD, "User.phones");
是否可以使用 Spring Data JPA 来做 smth。像这样:
public interface UserDao extends CrudRepository<User, Long> {
@EntityGraph(value = :graphName, type = EntityGraph.EntityGraphType.LOAD)
@Query(value = "SELECT DISTINCT u FROM User u")
List<User> findAllWithDetailsByGraphName(@Param(value="graphName") String graphName);
}
能够在 运行 时将 graphName 传递到方法中并使用一组需要的集合调用负载?此构造不起作用,产生编译时错误。任何围绕它的游戏也失败了...
因此,我在用户 class 中有多个集合,我想根据条件加载这些集合;
@Entity
@Table(name="user")
@NamedEntityGraphs({
@NamedEntityGraph(name = "User.details", attributeNodes = {
@NamedAttributeNode("phones"), @NamedAttributeNode("emails"), @NamedAttributeNode("pets")}),
@NamedEntityGraph(name = "User.phones", attributeNodes =
{@NamedAttributeNode("phones")}),
@NamedEntityGraph(name = "User.emails", attributeNodes =
{@NamedAttributeNode("emails")}),
@NamedEntityGraph(name = "User.pets", attributeNodes =
{@NamedAttributeNode("pets")})
})
public class User {
@Id
@GeneratedValue(strategy= GenerationType.AUTO, generator="native")
@GenericGenerator(name = "native", strategy = "native")
@Column(name="user_id")
private Long userId;
@Column(name="name")
private String name;
// more fields omitted
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Phone> phones;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Email> emails;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Pet> pets;
}
现在,我只需隐式声明所有方法,如下所示:
@EntityGraph(value = "User.phones", type = EntityGraph.EntityGraphType.LOAD)
@Query(value = "SELECT DISTINCT u FROM User u")
List<User> findAllWithPhones();
谢谢你的建议!
您可以定义一个接受实体图作为参数的基本 JPA 存储库。这在与 Specification
s 结合时特别有用。因此,下面是一个基于 Specification
s 的例子。也可以使用不同类型的参数构造其他查询。
@NoRepositoryBean
public interface MyBaseRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
T findOne(Specification<T> spec, EntityGraphType entityGraphType, String entityGraphName);
List<T> findAll(Specification<T> spec, Sort sort, EntityGraphType entityGraphType, String entityGraphName);
}
实施基本存储库:
@NoRepositoryBean
public class MyBaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyBaseRepository<T, ID> {
private EntityManager em;
public MyBaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.em = entityManager;
}
public MyBaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.em = em;
}
@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();
}
@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();
}
}
指定自定义基础存储库:
<jpa:repositories base-package="my.domain" base-class="my.repository.MyBaseRepositoryImpl" />
从自定义基础存储库扩展:
public interface UserRepository extends JpaRepository<User, Long>, MyBaseRepository<User, Long>, JpaSpecificationExecutor<User> {
}
使用自定义存储库的方法:
Specification mySpecs = ...
List<User> user = picklistRepository.findAll(mySpecs, EntityGraphType.LOAD, "User.phones");