Spring Data JPA:具有共享主键的OneToOne似乎不起作用

时间:2016-02-24 09:54:13

标签: java jpa spring-data-jpa one-to-one

使用Spring版本4.0.7中的Spring Data JPA,由Hibernate支持(通过导入Envers 4.3.6判断),我想在两个实体之间建立一对一的关系 - Payment和PaymentFailure。

付款失败时,会创建一个ID为Payment的PaymentFailure。尝试这样做时,我在使用StackOverflow和其他地方的任何推荐代码片段时会遇到各种错误。

例如,在使用@Id@MapsId时,我遇到了DataIntegrityViolationException

org.springframework.web.util.NestedServletException: Request processing failed;
    nested exception is org.springframework.dao.DataIntegrityViolationException:
        A different object with the same identifier value was already associated 
        with the session : [blah.payment.PaymentFailure#172656];
    nested exception is javax.persistence.EntityExistsException:
        A different object with the same identifier value was already associated
        with the session : [blah.payment.PaymentFailure#172656]

    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:170)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:137)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:141)

付款实体看起来像是:

import org.hibernate.annotations.DynamicInsert;
import org.hibernate.envers.Audited;
import org.hibernate.envers.NotAudited;
import javax.persistence.*;
import java.io.Serializable;

@Audited
@Entity
@Table(name = "payment")
@DynamicInsert
public class Payment implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @NotAudited
    @OneToOne(mappedBy = "payment", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private PaymentFailure paymentFailure;
    // ... other fields, setters ...
}

这是PaymentFailure:

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "payment_failure")
public class PaymentFailure implements Serializable {

    @Id
    private Long id;

    @MapsId
    @OneToOne
    @JoinColumn(name = "payment_id")
    private Payment payment;
    // ... getters, setters, other fields
}

我也尝试修改它,有人推荐在Hibernate JPA指南中提到的更好的版本,你没有单独的ID字段:

@Id
@OneToOne
@JoinColumn(name = "payment_id")
private Payment payment;

然而,由于IllegalArgumentException表示缺少注释@IdClass,因此无法加载,因此无法加载;但

Caused by: java.lang.IllegalArgumentException:
    This class [class blah.payment.PaymentFailure] does not define an IdClass

    at org.hibernate.jpa.internal.metamodel
        .AbstractIdentifiableType.getIdClassAttributes(AbstractIdentifiableType.java:200)
    at org.springframework.data.jpa.repository.support
        .JpaMetamodelEntityInformation$IdMetadata.<init>(JpaMetamodelEntityInformation.java:221)
    at org.springframework.data.jpa.repository.support
        .JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:79)
    at org.springframework.data.jpa.repository.support
        .JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65)
    at org.springframework.data.jpa.repository.support
        .JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:149)
    at org.springframework.data.jpa.repository.support
        .JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:88)
    at org.springframework.data.jpa.repository.support
        .JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:68)
    at org.springframework.data.repository.core.support
        .RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:158)
    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:1613)
    at org.springframework.beans.factory.support
        .AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)

是否有一些方法可以在我的设置中使用?或者,它可能适用于更高版本的Spring或Hibernate吗?我现在真的输了,我已经阅读了很多建议,但都没有。

1 个答案:

答案 0 :(得分:-1)

@OneToOne
@JoinColumn(name = "payment_id")
@ForeignKey
private Payment payment;

您可以在此处使用@ForeignKey注释。 编辑 -

@OneToOne
@JoinColumn(name = "payment_id", foreignKey = @ForeignKey(name = "FK_NAME"))
private Payment payment;