Spring 4 - 配置 XML jpa:repositories 抛出 NoSuchMethodError BeanDefinitionParserDelegate.getEnvironment()

Spring 4 - Config XML jpa:repositories throwing NoSuchMethodError BeanDefinitionParserDelegate.getEnvironment()

我正在尝试将 Gradle 项目 here 集成到我的 Maven 项目中。文件 data-context.xml 用于使用 Spring 配置 Hibernate 以生成用于验证用户对 RESTful 接口的请求的存储库。

一切正常,但当我尝试部署到 tomcat 服务器时,我看到以下问题:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityContextFilter' defined in file [/var/lib/tomcat6/webapps/services/WEB-INF/classes/com/services/filter/SecurityContextFilter.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.services.user.UserRepository]: : Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract com.services.user.domain.User com.services.user.UserRepository.findBySession(java.lang.String)!; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract com.services.user.domain.User com.services.user.UserRepository.findBySession(java.lang.String)!
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1139) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) ~[spring-context-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4210) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4709) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:526) [catalina-6.0.24.jar:na]
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:905) [catalina-6.0.24.jar:na]
    at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:740) [catalina-6.0.24.jar:na]
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:500) [catalina-6.0.24.jar:na]
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1277) [catalina-6.0.24.jar:na]
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:321) [catalina-6.0.24.jar:na]
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:722) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.StandardService.start(StandardService.java:516) [catalina-6.0.24.jar:na]
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:710) [catalina-6.0.24.jar:na]
    at org.apache.catalina.startup.Catalina.start(Catalina.java:593) [catalina-6.0.24.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_79]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_79]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_79]
    at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_79]
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289) [bootstrap-6.0.24.jar:na]
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414) [bootstrap-6.0.24.jar:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract com.services.user.domain.User com.services.user.UserRepository.findBySession(java.lang.String)!
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
... 39 common frames omitted
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract com.services.user.domain.User com.services.user.UserRepository.findBySession(java.lang.String)!
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:92) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:62) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:72) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:53) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:136) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:204) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:73) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:347) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:185) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    ... 50 common frames omitted
Caused by: java.lang.NullPointerException: null
    at org.hibernate.internal.util.StringHelper.root(StringHelper.java:345) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.getSubclassPropertyTableNumber(AbstractEntityPersister.java:1994) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.persister.entity.BasicEntityPropertyMapping.toColumns(BasicEntityPropertyMapping.java:61) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.toColumns(AbstractEntityPersister.java:1970) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.tree.FromElement.getIdentityColumns(FromElement.java:355) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.tree.IdentNode.resolveAsAlias(IdentNode.java:167) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.tree.IdentNode.resolve(IdentNode.java:104) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:126) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:121) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:959) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.propertyRef(HqlSqlBaseWalker.java:1146) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectExpr(HqlSqlBaseWalker.java:2253) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectExprList(HqlSqlBaseWalker.java:2194) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectClause(HqlSqlBaseWalker.java:1476) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:573) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1836) ~[hibernate-core-4.3.10.Final.jar:4.3.10.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:328) ~[hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_79]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_79]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_79]
    at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_79]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:344) ~[spring-orm-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at com.sun.proxy.$Proxy50.createQuery(Unknown Source) ~[na:na]
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:86) ~[spring-data-jpa-1.8.0.RELEASE.jar:na]
    ... 63 common frames omitted

我倾向于认为这是由于data-context.xml没有正确初始化导致查询验证失败。下面是我的代码示例,以及我在 pom 中包含的 spring 依赖项。

数据-context.xml-

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jpa="http://www.springframework.org/schema/data/jpa"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/integration/jdbc
    http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/data/repository
    http://www.springframework.org/schema/data/repository/spring-repository.xsd">

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="samplePersistenceUnit"/>
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>

</bean>

<jpa:repositories base-package="com.services.user" />
<!-- 
    the above shows the following error in Eclipse  :
    java.lang.NoSuchMethodError: org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.getEnvironment()
 -->

<bean class="org.springframework.orm.jpa.JpaTransactionManager"
      id="transactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    </property>
</bean>

<tx:annotation-driven/>
...
</beans>

Domain.User class -

@Entity
@Table(name="rest_user")
public class User extends BaseEntity {

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

private static final int HASH_ITERATIONS = 1000;
private String firstName;
private String lastName;
private String emailAddress;
private String hashedPassword;
private boolean isVerified;

@Enumerated(EnumType.STRING)
private Role role;

@OneToMany(mappedBy="user",
             targetEntity=VerificationToken.class,
             cascade= CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
private List<VerificationToken> verificationTokens = new ArrayList<VerificationToken>();

@OneToOne(fetch = FetchType.LAZY,
        mappedBy = "user",
        cascade = CascadeType.ALL)
private AuthorizationToken authorizationToken;

Domain.AuthorizationToken class -

@Entity
@Table(name="rest_authorization_token")
public class AuthorizationToken extends AbstractPersistable<Long> {

private final static Integer DEFAULT_TIME_TO_LIVE_IN_SECONDS = (60 * 60 * 24 * 30); //30 Days

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

@Column(length=36)
private String token;

private Date timeCreated;

private Date expirationDate;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "token")
private User user;

UserRepository class -

public interface UserRepository  extends JpaRepository<User, Long> {

User findByEmailAddress(String emailAddress);

@Query("select u from User u where uuid = ?")
User findByUuid(String uuid);

@Query("select u from User u where u in (select user from AuthorizationToken where lastUpdated < ?)")
List<User> findByExpiredSession(Date lastUpdated);

@Query("select u from User u where u = (select user from AuthorizationToken where token = ?)")
User findBySession(String token);

}

VerificationToken class -

@Entity
@Table(name = "rest_verification_token")
public class VerificationToken extends BaseEntity {

private static final int DEFAULT_EXPIRY_TIME_IN_MINS = 60 * 24; //24 hours

@Column(length=36)
private String token;

private Date expiryDate;

@Enumerated(EnumType.STRING)
private VerificationTokenType tokenType;

private boolean verified;

@ManyToOne
User user;

public VerificationToken() {
    super();
    this.token = UUID.randomUUID().toString();
    this.expiryDate = calculateExpiryDate(DEFAULT_EXPIRY_TIME_IN_MINS);
}

public VerificationToken(User user, VerificationTokenType tokenType, int expirationTimeInMinutes) {
    this();
    this.user = user;
    this.tokenType = tokenType;
    this.expiryDate = calculateExpiryDate(expirationTimeInMinutes);
}

pom.xml Spring 依赖项-(我确定没有冲突)

对于初学者,我建议修复你的实体,你有一个基本的一对一映射,但你正在让它变得复杂,而且你不需要复合主键。接下来你的查询也很复杂你不需要连接你可以简单地 return 来自 AuthorizationToken.

user 字段

实体

您的所有实体都直接或间接扩展 AbstractPersistable class 已经有一个 id 字段。不需要添加额外的 @Id 并且只会混淆 JPA,因为您现在突然需要一个复合主键。解决方案很容易从实体中删除自定义 id 字段。

@Entity
@Table(name="rest_authorization_token")
public class AuthorizationToken extends AbstractPersistable<Long> {

    @Column(length=36)
    private String token;

    @OneToOne(fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn
    private User user;

}

AuthorizationToken 不可嵌入,因此删除注释。对于一对一映射,添加 @PrimaryKeyJoinColumn 注释。 token 字段不需要是 @Id AbstractPersistable 中已经有一个主键字段。

User 实体上删除 @IdClass,因为简单映射不需要它。如果您不想要双向关系,请从 User 实体中删除 authorizationToken 字段。如果你想使用它,只需删除 @Id.

@Entity 
@Table(name="rest_user")
public class User extends BaseEntity {

    @OneToOne(fetch = FetchType.LAZY,
            mappedBy = "user",
            cascade = CascadeType.ALL)
    private AuthorizationToken authorizationToken;

}

注意:我省略了其余的实体代码,因为它们保持不变。

现在实体已经清理完毕,只需 returning AuthorizationToken 中的 user 字段即可简化查询。

public interface UserRepository extends JpaRepository<User, Long> {

    User findByEmailAddress(String emailAddress);

    User findByUuid(String uuid);

    @Query("select user from AuthorizationToken where lastUpdated < ?")
    List<User> findByExpiredSession(Date lastUpdated);

    @Query("select user from AuthorizationToken where token = ?")
    User findBySession(String token);

}

我还注意到您有 findByUuid@Query 不需要,因为 Spring Data JPA 可以为您生成该查询。