【问题标题】:Spring 4 - Config XML jpa:repositories throwing NoSuchMethodError BeanDefinitionParserDelegate.getEnvironment()Spring 4 - 配置 XML jpa:存储库抛出 NoSuchMethodError BeanDefinitionParserDelegate.getEnvironment()
【发布时间】:2015-07-01 19:47:39
【问题描述】:

我正在尝试将 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$1.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$1.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 依赖项。

数据上下文.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 类 -

@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 类 -

@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 类 -

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 类 -

@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 依赖项-(我已确保没有冲突)

【问题讨论】:

  • 请添加 fullstracktrace 而不是 sn-p。
  • 更新了完整的 stracktrace,如 tomcat 日志中所示。
  • 对不起,那里的跟踪不正确。我会在 1 分钟内更新。
  • 您的查询不是很无聊,您的配置不是很复杂吗?以下查询应该在没有子选择 select u from User u where u. authorizationToken.token=? 的情况下工作,同样适用于过期会话的查询。不确定您是否需要@IdClass,但这是来自我的观点。另一个可以工作的查询select at.user from AuthorizationToken at where at.token=? 不需要加入,同样适用于会话。
  • 我也没有得到的是你使用 Spring Boot 但正在部署。你能展示一下你的扩展SpringBootServletInitializer的类是什么样子的吗?

标签: spring hibernate spring-data spring-4


【解决方案1】:

对于初学者,我建议修复你的实体,你有一个基本的一对一映射,但你让它变得复杂,你也不需要复合主键。接下来,您的查询也很复杂,您不需要连接,您只需从 AuthorizationToken 返回 user 字段。

实体

您的所有实体都直接或间接地扩展 AbstractPersistable 该类已经有一个 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 字段不需要是@IdAbstractPersistable 中已经有一个主键字段。

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;

}

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

现在实体已清理完毕,只需从 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);

}

我还注意到您有一个 @Query 用于 findByUuid,这是不需要的,因为 Spring Data JPA 可以为您生成该查询。

【讨论】:

  • 非常感谢!!通过一些解释,代码更容易理解。你帮了大忙
  • 已经彻底修复了AuthorizationToken错误,实体创建成功。现在它卡在 VerificationToken 上并出现类似问题 - org.hibernate.MappingException: property mapping has wrong number of columns: com.services.user.domain.VerificationToken.user,我曾希望用相同的逻辑解决这个问题,但没有运气
  • 将其添加到您的问题中,以查看映射是否有任何问题。在VerificationTokenuser 字段中添加一个简单的@ManyToOne 就足够了。
  • 在失败的运行中,我意识到我在用户字段中留下了一个 id。当我删除它时,eclipse 错误日志告诉我该实体没有 PK 字段,即使我正在扩展 AbstractPersistable。我的 VerficationToken 类也是如此,如果我删除声明的 Id 字段,则该实体在 Eclipse 中无效
  • 有时您应该忽略 Eclipse 中的错误(有时检测错误有点粗略)。只需编译并运行您的应用程序,看看它是否有效(我希望如此)。
猜你喜欢
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 1970-01-01
  • 2018-01-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 2013-04-22
相关资源
最近更新 更多