如何查询复合主键的子集?
How to query on subset of composite primary key?
我有以下 类:
@Entity
@Table(name = "my_entity")
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyEntity {
@EmbeddedId
private Pk id;
public Pk getId() {
return id;
}
public void setId(Pk id) {
this.id = id;
}
}
@Embeddable
public class Pk implements Serializable {
private static final long serialVersionUID = -3090221844117493661L;
private Integer type;
private String userId;
public Pk() {
}
public Pk(String userId, Integer type) {
this.setUserId(userId);
this.setType(type);
}
public Integer getType() {
return type;
}
public String getUserId() {
return userId;
}
public void setType(Integer type) {
this.type = type;
}
public void setUserId(String userId) {
this.userId = userId;
}
// Auto-generated by Eclipse.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((userId == null) ? 0 : userId.hashCode());
return result;
}
// Auto-generated by Eclipse.
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pk other = (Pk) obj;
if (type != other.type)
return false;
if (userId == null) {
if (other.userId != null)
return false;
} else if (!userId.equals(other.userId))
return false;
return true;
}
}
public interface MyEntityRepository extends JpaRepository<MyEntity, Pk> {
List<MyEntity> findAllByUserId(String userId);
}
当我初始化 Spring 数据 JPA 时出现错误:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myEntityRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property user found for type MyEntity!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1512)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:615)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:73)
at com.myproject.backend.common.ServiceContext.start(ServiceContext.java:293)
at com.myproject.run(AbstractServiceContainer.java:55)
at com.myproject..run(AbstractServiceContainer.java:1)
at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:42)
at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:76)
at io.dropwizard.cli.Cli.run(Cli.java:70)
at io.dropwizard.Application.run(Application.java:72)
at com.myproject..main(CombinedServiceContainer.java:106)
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property user found for type MyEntity!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:213)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:321)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:301)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:85)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:60)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:91)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:168)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:69)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:320)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:169)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:224)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:210)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 18 more
问题:Data JPA 是否 Spring 不支持查询主键的子集?或者我是否需要为此实现自定义存储库方法?
好的,我也尝试用 @IdClass
代替:
@Entity
@Table(name = "my_entity")
@JsonIgnoreProperties(ignoreUnknown = true)
@IdClass(Pk.class)
public class MyEntity {
@Id private Integer type;
@Id private String userId;
public Pk getId() {
return id;
}
public void setId(Pk id) {
this.id = id;
}
}
@IdClass(Pk.class)
public class Pk implements Serializable {
private static final long serialVersionUID = -3090221844117493661L;
private Integer type;
private String userId;
public Pk() {
}
public Pk(String userId, Integer type) {
this.setUserId(userId);
this.setType(type);
}
public Integer getType() {
return type;
}
public String getUserId() {
return userId;
}
public void setType(Integer type) {
this.type = type;
}
public void setUserId(String userId) {
this.userId = userId;
}
// Auto-generated by Eclipse.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((userId == null) ? 0 : userId.hashCode());
return result;
}
// Auto-generated by Eclipse.
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pk other = (Pk) obj;
if (type != other.type)
return false;
if (userId == null) {
if (other.userId != null)
return false;
} else if (!userId.equals(other.userId))
return false;
return true;
}
}
这确实给了我一条不同的错误消息,一个 NullPointerException
,它向我暗示 Spring Data JPA 无法为 findAllByUserId(...)
构建查询。我对该查询方法进行了自定义实现:
public interface MyEntityRepository extends JpaRepository<MyEntity, Pk>, MyEntityRepositoryCustom {
}
public interface MyEntityRepositoryCustom {
List<MyEntity> findAllByUserId(String userId);
}
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public List<MyEntityRepositoryCustom> findAllByUserId(String userId) {
return em
.createQuery("select o from MyEntity o where o.userId=:userId",
MyEntity.class).setParameter("userId", userId).getResultList();
}
}
...瞧,有效!
您需要告诉 JPA 在哪里查找 userId 字段(即在嵌入式 ID 中)。
如果将存储库方法的名称更改为 findAllByIdUserId
,它应该可以工作。
我有以下 类:
@Entity
@Table(name = "my_entity")
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyEntity {
@EmbeddedId
private Pk id;
public Pk getId() {
return id;
}
public void setId(Pk id) {
this.id = id;
}
}
@Embeddable
public class Pk implements Serializable {
private static final long serialVersionUID = -3090221844117493661L;
private Integer type;
private String userId;
public Pk() {
}
public Pk(String userId, Integer type) {
this.setUserId(userId);
this.setType(type);
}
public Integer getType() {
return type;
}
public String getUserId() {
return userId;
}
public void setType(Integer type) {
this.type = type;
}
public void setUserId(String userId) {
this.userId = userId;
}
// Auto-generated by Eclipse.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((userId == null) ? 0 : userId.hashCode());
return result;
}
// Auto-generated by Eclipse.
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pk other = (Pk) obj;
if (type != other.type)
return false;
if (userId == null) {
if (other.userId != null)
return false;
} else if (!userId.equals(other.userId))
return false;
return true;
}
}
public interface MyEntityRepository extends JpaRepository<MyEntity, Pk> {
List<MyEntity> findAllByUserId(String userId);
}
当我初始化 Spring 数据 JPA 时出现错误:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myEntityRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property user found for type MyEntity!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1512)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:615)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:73)
at com.myproject.backend.common.ServiceContext.start(ServiceContext.java:293)
at com.myproject.run(AbstractServiceContainer.java:55)
at com.myproject..run(AbstractServiceContainer.java:1)
at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:42)
at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:76)
at io.dropwizard.cli.Cli.run(Cli.java:70)
at io.dropwizard.Application.run(Application.java:72)
at com.myproject..main(CombinedServiceContainer.java:106)
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property user found for type MyEntity!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:359)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:213)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:321)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:301)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:85)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:60)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:91)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:168)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:69)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:320)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:169)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:224)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:210)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 18 more
问题:Data JPA 是否 Spring 不支持查询主键的子集?或者我是否需要为此实现自定义存储库方法?
好的,我也尝试用 @IdClass
代替:
@Entity
@Table(name = "my_entity")
@JsonIgnoreProperties(ignoreUnknown = true)
@IdClass(Pk.class)
public class MyEntity {
@Id private Integer type;
@Id private String userId;
public Pk getId() {
return id;
}
public void setId(Pk id) {
this.id = id;
}
}
@IdClass(Pk.class)
public class Pk implements Serializable {
private static final long serialVersionUID = -3090221844117493661L;
private Integer type;
private String userId;
public Pk() {
}
public Pk(String userId, Integer type) {
this.setUserId(userId);
this.setType(type);
}
public Integer getType() {
return type;
}
public String getUserId() {
return userId;
}
public void setType(Integer type) {
this.type = type;
}
public void setUserId(String userId) {
this.userId = userId;
}
// Auto-generated by Eclipse.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((userId == null) ? 0 : userId.hashCode());
return result;
}
// Auto-generated by Eclipse.
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pk other = (Pk) obj;
if (type != other.type)
return false;
if (userId == null) {
if (other.userId != null)
return false;
} else if (!userId.equals(other.userId))
return false;
return true;
}
}
这确实给了我一条不同的错误消息,一个 NullPointerException
,它向我暗示 Spring Data JPA 无法为 findAllByUserId(...)
构建查询。我对该查询方法进行了自定义实现:
public interface MyEntityRepository extends JpaRepository<MyEntity, Pk>, MyEntityRepositoryCustom {
}
public interface MyEntityRepositoryCustom {
List<MyEntity> findAllByUserId(String userId);
}
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public List<MyEntityRepositoryCustom> findAllByUserId(String userId) {
return em
.createQuery("select o from MyEntity o where o.userId=:userId",
MyEntity.class).setParameter("userId", userId).getResultList();
}
}
...瞧,有效!
您需要告诉 JPA 在哪里查找 userId 字段(即在嵌入式 ID 中)。
如果将存储库方法的名称更改为 findAllByIdUserId
,它应该可以工作。