Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我的JPA@OneToOne关系导致在目标实体上插入而不是更新_Jpa_Spring Data Jpa - Fatal编程技术网

我的JPA@OneToOne关系导致在目标实体上插入而不是更新

我的JPA@OneToOne关系导致在目标实体上插入而不是更新,jpa,spring-data-jpa,Jpa,Spring Data Jpa,我有一个成员实体,它与地址实体有@OneToOne关系,如下所示: public void modifyAddress(Member member, Address address){ member.setAddress(address); memberRepository.save(member); } 在成员实体中: @OneToOne(cascade=CascadeType.ALL) private Address address; @RooJp

我有一个
成员
实体,它与
地址
实体有
@OneToOne
关系,如下所示:

public void modifyAddress(Member member, Address address){
        member.setAddress(address);
        memberRepository.save(member);
    }
成员
实体中:

@OneToOne(cascade=CascadeType.ALL)
private Address address;
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;
}
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
    private Member member;
}
@OneToOne
private Address address;
地址
实体:

@OneToOne(cascade=CascadeType.ALL)
private Address address;
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;
}
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
    private Member member;
}
@OneToOne
private Address address;
我遇到的问题是,每次我更新成员的地址如下:

public void modifyAddress(Member member, Address address){
        member.setAddress(address);
        memberRepository.save(member);
    }
它不更新地址表中的行,而是在地址表中插入新行,并更新成员表中的FK,如下面给出的sql中所示:

生成的SQL:

Hibernate: 
    /* insert com.bignibou.domain.Address
        */ insert 
        into
            address
            (formatted_address, latitude, longitude, version) 
        values
            (?, ?, ?, ?)
Hibernate: 
    /* update
        com.bignibou.domain.Member */ update
            member 
        set
            address=?,
            version=? 
        where
            id=? 
            and version=?
我不确定如何解决这个问题(我现在不想在成员表中内联地址数据)。我想让我的应用程序更新地址表,而不是在该表中插入新行

有人能给我建议吗

编辑1

我对我的实体进行了如下修改:

public void modifyAddress(Member member, Address address){
        member.setAddress(address);
        memberRepository.save(member);
    }
以下是完整的
地址
实体:

@OneToOne(cascade=CascadeType.ALL)
private Address address;
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;
}
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
    private Member member;
}
@OneToOne
private Address address;
以下是
成员
实体中的相关属性:

@OneToOne(cascade=CascadeType.ALL)
private Address address;
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;
}
@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
    private Member member;
}
@OneToOne
private Address address;
我的方法:

@Override
public void modifyAddress(Member member, Address address){
    address.setMember(member);
    updateAddress(address);
}
我的应用程序的行为保持不变

编辑2:如果我按以下方式修改应用程序,我会得到一个StaleObjectStateException

@Override
    public void modifyAddress(Member member, Address address){
        long addressId = member.getAddress().getId();
        address.setId(addressId);
        address.setMember(member);
        updateAddress(address);
    }
地址:

@RooJpaEntity
public class Address {

    private String formattedAddress;
    private double latitude;
    private double longitude;

    @OneToOne
    private Member member;
}
成员:

@OneToOne
private Address address;
StaleObjectStateException:

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.bignibou.domain.Address#5]
    org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:303)
    org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151)
    org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76)
    org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:903)
    org.hibernate.internal.SessionImpl.merge(SessionImpl.java:887)
    org.hibernate.internal.SessionImpl.merge(SessionImpl.java:891)
    org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:879)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:601)
    org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:366)
    com.sun.proxy.$Proxy49.merge(Unknown Source)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:601)
    org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
    com.sun.proxy.$Proxy48.merge(Unknown Source)
    org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:353)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:601)
    org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:333)
    org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:318)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    com.sun.proxy.$Proxy65.save(Unknown Source)
    com.bignibou.service.PreferencesServiceImpl_Roo_Service.ajc$interMethod$com_bignibou_service_PreferencesServiceImpl_Roo_Service$com_bignibou_service_PreferencesServiceImpl$updateAddress(PreferencesServiceImpl_Roo_Service.aj:53)
    com.bignibou.service.PreferencesServiceImpl.updateAddress(PreferencesServiceImpl.java:1)
    com.bignibou.service.PreferencesServiceImpl_Roo_Service.ajc$interMethodDispatch1$com_bignibou_service_PreferencesServiceImpl_Roo_Service$com_bignibou_service_PreferencesServiceImpl$updateAddress(PreferencesServiceImpl_Roo_Service.aj)
    com.bignibou.service.PreferencesServiceImpl.modifyAddress_aroundBody12(PreferencesServiceImpl.java:100)
    com.bignibou.service.PreferencesServiceImpl$AjcClosure13.run(PreferencesServiceImpl.java:1)
    org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59)
    org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
    com.bignibou.service.PreferencesServiceImpl.modifyAddress(PreferencesServiceImpl.java:93)
    com.bignibou.controller.PreferenceController.modifyAddress(PreferenceController.java:168)
编辑3

地址的哈希代码:

public int hashCode() {
        return new HashCodeBuilder().append(formattedAddress).append(getId()).append(latitude).append(longitude).toHashCode();
    }
地址等于(来自ITD):

地址实体的ITD:

privileged aspect Address_Roo_Jpa_Entity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long Address.id;

    @Version
    @Column(name = "version")
    private Integer Address.version;

    public Long Address.getId() {
        return this.id;
    }

    public void Address.setId(Long id) {
        this.id = id;
    }

    public Integer Address.getVersion() {
        return this.version;
    }

    public void Address.setVersion(Integer version) {
        this.version = version;
    }

}
顺便说一下,ITD只是方面

编辑4:我已经在这里为您设置了一个示例应用程序:

(我删除了错误的原始诊断,我还是让链接继续运行,因为它们仍然具有指导性)

见:和

编辑:

  • 实际上,您得到StaleObjectStateException是因为您正在修改现有实体的主键
  • 如果您恢复到原始(且正确)配置(成员拥有单向OneToOne关系)。
    通过保存成员并执行以下操作,可以更新地址表:
    • 保存地址为a0的成员m0
    • 冲洗
    • 检索m0.a0并编辑值
    • 保存m0
    • 保存没有地址m1的成员
    • 保存地址a1
    • 冲洗
    • 将a1连接到m1,保存m1
    • 使用地址a2保存成员m2
    • 冲洗
    • 将m2地址设置为空
    • 保存m2,此处a2将被更新并保持为没有关联成员(孤立),您可以使用关系上的删除孤立选项强制在这种情况下删除a2
Ofc,仅当操作发生在同一事务中时才需要这里的刷新调用

所有这些都可以通过示例应用程序正常运行

请注意一件有趣的事情,OneToOne关系本身并不能确保地址和成员之间的唯一性。(您可以有两个成员引用同一地址)。您必须使用
@JoinColumn(name=“address”,unique=true)

(我删除了错误的原始诊断,我还是让链接显示,因为它们仍然具有指导意义)

见:和

编辑:

  • 实际上,您得到StaleObjectStateException是因为您正在修改现有实体的主键
  • 如果您恢复到原始(且正确)配置(成员拥有单向OneToOne关系)。
    通过保存成员并执行以下操作,可以更新地址表:
    • 保存地址为a0的成员m0
    • 冲洗
    • 检索m0.a0并编辑值
    • 保存m0
    • 保存没有地址m1的成员
    • 保存地址a1
    • 冲洗
    • 将a1连接到m1,保存m1
    • 使用地址a2保存成员m2
    • 冲洗
    • 将m2地址设置为空
    • 保存m2,此处a2将被更新并保持为没有关联成员(孤立),您可以使用关系上的删除孤立选项强制在这种情况下删除a2
Ofc,仅当操作发生在同一事务中时才需要这里的刷新调用

所有这些都可以通过示例应用程序正常运行


请注意一件有趣的事情,OneToOne关系本身并不能确保地址和成员之间的唯一性。(您可以有两个成员引用同一地址)。您必须使用
@JoinColumn(name=“address”,unique=true)显式显示唯一约束。我本以为
成员
是关系的拥有方,而不是
地址
目前的状况……试试这个Hi-Gab。我肯定被困在这里了。我已按照编辑中的说明修改了我的应用程序,但没有效果。你能帮忙吗?就id字段而言,它位于其他地方的某个方面,但它已被考虑在内。否则我会得到可怕的StaleObjectStateException…StaleObjectStateException是一个乐观锁定异常。嗨。我本以为
成员
是关系的拥有方,而不是
地址
目前的状况……试试这个Hi-Gab。我肯定被困在这里了。我已按照编辑中的说明修改了我的应用程序,但没有效果。你能帮忙吗?就id字段而言,它位于其他地方的某个方面,但它已被考虑在内。否则我会得到可怕的StaleObjectStateException…StaleObjectStateException是一个乐观锁定异常。