Java 保持一对多关系时的约束冲突

Java 保持一对多关系时的约束冲突,java,mysql,spring,hibernate,jpa,Java,Mysql,Spring,Hibernate,Jpa,在使用hibernate和MySQL的spring mvc应用程序中,我得到以下约束冲突异常: Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`mybd`.`hl7_documententity`, CONSTRAINT `hl7_

在使用hibernate和MySQL的spring mvc应用程序中,我得到以下约束冲突异常:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:  
Cannot add or update a child row: a foreign key constraint fails  
(`mybd`.`hl7_documententity`, CONSTRAINT `hl7_documententity_ibfk_1`   
FOREIGN KEY (`ptcode`, `ptcodesystem`)    
REFERENCES `hl7_generalcode` (`code`, `codesystem`))
当我试图保存一个包含
GeneralCode
类型属性的
DocumentEntity
时,就会出现问题,这两个属性的定义如下

我读过很多关于这个错误的帖子和博客,但似乎没有一个能解决我的问题如何解决此错误?

以下是
DocumentEntity
类:

@Entity
@Table(name = "hl7_documententity")
public class HL7DocumentEntity extends BaseEntity{

    //other properties

    @ManyToOne
    @JoinColumns({ @JoinColumn(name = "ptcode", referencedColumnName = "code"),
        @JoinColumn(name = "ptcodesystem", referencedColumnName = "codesystem")
    })
    private HL7GeneralCode providertype;

    //getters and setters    
}
@Entity
@Table(name = "hl7_generalcodes")
public class HL7GeneralCode implements Serializable{

    private static final long serialVersionUID = -8620565054475096516L;

    @EmbeddedId
    private HL7EmbedCodePK codePk;

    @OneToMany(mappedBy = "providertype")
    private Set<HL7DocumentEntity> documententities;

    ////////////getters and setters    
}
以下是
GeneralCode
类:

@Entity
@Table(name = "hl7_documententity")
public class HL7DocumentEntity extends BaseEntity{

    //other properties

    @ManyToOne
    @JoinColumns({ @JoinColumn(name = "ptcode", referencedColumnName = "code"),
        @JoinColumn(name = "ptcodesystem", referencedColumnName = "codesystem")
    })
    private HL7GeneralCode providertype;

    //getters and setters    
}
@Entity
@Table(name = "hl7_generalcodes")
public class HL7GeneralCode implements Serializable{

    private static final long serialVersionUID = -8620565054475096516L;

    @EmbeddedId
    private HL7EmbedCodePK codePk;

    @OneToMany(mappedBy = "providertype")
    private Set<HL7DocumentEntity> documententities;

    ////////////getters and setters    
}
以下是dao方法:

@Repository
public class JpaSomethingRepositoryImpl implements SomethingRepository {

    @PersistenceContext
    private EntityManager em;

    @Override
    @Transactional
    public void savehl7DocumentEntity(HL7DocumentEntity de) {
        HL7GeneralCode code = de.getProvidertype();
        if(code !=null && code.getCodePk()==null){//HL7GeneralCode is not persistent. We don't support that
            throw new IllegalStateException("Cannot persist an adress using a non persistent HL7GeneralCode");
        }
        System.out.println("=========================== inside jpaCdaRespository.saveDocEntity(de)");
        de.setProvidertype(null);
        if(code.getDocumententities()!=null){
            ArrayList<HL7DocumentEntity> addrList = new ArrayList<HL7DocumentEntity>();
            addrList.addAll(code.getDocumententities());
            addrList.remove(de);
            Set<HL7DocumentEntity> myaddrs = new HashSet<HL7DocumentEntity>(addrList);
            code.setDocumententities(myaddrs);
        }
        code = em.merge(code); 
        de.setProvidertype(code);
        code.addDocumententity(de);

        if (de.getId() == null) {
            System.out.println("[[[[[[[[[[[[ about to persist de ]]]]]]]]]]]]]]]]]]]]");
            em.persist(de);
        } else {
            System.out.println("]]]]]]]]]]]]]]]]]] about to merge de [[[[[[[[[[[[[[[[[[[[[");
            de = em.merge(de);
        }
    }
}
@存储库
公共类JpaSomethingRepositoryImpl实现了一些东西存储库{
@持久上下文
私人实体管理者;
@凌驾
@交易的
公共作废保存HL7DocumentEntity(HL7DocumentEntity de){
HL7GeneralCode代码=de.getProvidertype();
如果(code!=null&&code.getCodePk()==null){//HL7GeneralCode不是持久性的。我们不支持这一点
抛出新的非法状态异常(“无法使用非持久性HL7GeneralCode持久化地址”);
}
System.out.println(“===========================================内部jpaCdaRespository.saveDocEntity(de)”);
de.setProvidertype(空);
if(code.getDocumententities()!=null){
ArrayList addrList=新的ArrayList();
addrList.addAll(code.getDocumententities());
addrList.remove(de);
Set myaddrs=newhashset(addrList);
代码。setDocumententities(myaddrs);
}
代码=em.merge(代码);
de.setProvidertype(代码);
代码.addDocumententity(de);
if(de.getId()==null){
System.out.println(“[][][[][[][[D][T][[D][T][T][T][T][T][T][T][D][T][T][T][T][T][T][T][T][T][D][D][T][D][T][D][;
em.persist(de);
}否则{
System.out.println(“:/][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][;
de=em.merge(de);
}
}
}
执行的SQL语句和hibernate试图通过SQL插入的实际值为:

[[[[[[[[[[[[ about to persist de ]]]]]]]]]]]]]]]]]]]]
DEBUG SQL - insert into hl7_documententity (author_id, authpar_id, entitytype, id_extension, id_root, ptcode, ptcodesystem, id) values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into hl7_documententity (author_id, authpar_id, entitytype, id_extension, id_root, ptcode, ptcodesystem, id) values (?, ?, ?, ?, ?, ?, ?, ?)
TRACE BasicBinder - binding parameter [1] as [INTEGER] - <null>
TRACE BasicBinder - binding parameter [2] as [INTEGER] - <null>
TRACE BasicBinder - binding parameter [3] as [VARCHAR] - <null>
TRACE BasicBinder - binding parameter [4] as [VARCHAR] - NI
TRACE BasicBinder - binding parameter [5] as [VARCHAR] - nullFlavor
TRACE BasicBinder - binding parameter [6] as [VARCHAR] - UNK
TRACE BasicBinder - binding parameter [7] as [VARCHAR] - HL7NullFlavor
TRACE BasicBinder - binding parameter [8] as [INTEGER] - 32787
WARN  SqlExceptionHelper - SQL Error: 1452, SQLState: 23000
ERROR SqlExceptionHelper - Cannot add or update a child row: a foreign key constraint fails (`docbd`.`hl7_documententity`, CONSTRAINT `hl7_documententity_ibfk_1` FOREIGN KEY (`ptcode`, `ptcodesystem`) REFERENCES `hl7_generalcode` (`code`, `codesystem`))
INFO  AbstractBatchImpl - HHH000010: On release of batch it still contained JDBC statements
WARN  warn - Handler execution resulted in exception
[][[][[][[][[de][]]]]]]]]]]]]]]]]]]]]]][[de][]]]]]]]]]]]]][[de][code][]]]]]]]]]]-[de][code][
调试SQL-插入hl7_documententity(author_id、authpar_id、entitytype、id_扩展、id_根、ptcode、ptcodesystem、id)值(?,,,,,,,,,?)
Hibernate:插入hl7_documententity(author_id、authpar_id、entitytype、id_扩展、id_根、ptcode、ptcodesystem、id)值(?,,,,,,,,,?)
跟踪BasicBinder-将参数[1]绑定为[INTEGER]-
跟踪BasicBinder-将参数[2]绑定为[INTEGER]-
TRACE BasicBinder-绑定参数[3]为[VARCHAR]-
TRACE BasicBinder-绑定参数[4]为[VARCHAR]-NI
跟踪BasicBinder-绑定参数[5]为[VARCHAR]-nullFlavor
TRACE BasicBinder-绑定参数[6]为[VARCHAR]-UNK
跟踪BasicBinder-绑定参数[7]为[VARCHAR]-HL7NullFlavor
跟踪BasicBinder-绑定参数[8]为[INTEGER]-32787
警告SqlExceptionHelper-SQL错误:1452,SQLState:23000
错误SqlExceptionHelper-无法添加或更新子行:外键约束失败(`docbd`.`hl7\u documententity`,约束`hl7\u documententity\u ibfk\u 1`外键(`ptcode`,`ptcodesystem`)引用`hl7\u generalcode`(`code`,`codesystem`)
InfoAbstractBatchImpl-hh000010:batch发布时,它仍然包含JDBC语句
警告-处理程序执行导致异常
您可以阅读EmbeddeCodePK类代码。
您可以读取整个堆栈跟踪。

到BaseEntity类的代码。

您知道,我将首先清理此代码

虽然hibernate文档可能会告诉您,将这些注释放在字段变量上是可以的,,,但作为一个标准,这不是一个好主意。字段级别要求hibernate在惰性抓取的情况下访问字段之前创建一个代理。因此,只要习惯于正确操作,您就不会不幸发现问题。全部移动那些作为属性级访问的getter注释不需要代理

字段级变量应该是私有的

你在那里把一个整数转换成一个整数…有些东西让我不想看它,老实说,可能会有一点愚蠢的懒惰,最终成为你的问题


当您正在使用时,继续使用新的HashSet(0)初始化集合;类似的事情。仍然会更新我们。

您知道我将首先清理此代码

虽然hibernate文档可能会告诉您,将这些注释放在字段变量上是可以的,,,但作为一个标准,这不是一个好主意。字段级别要求hibernate在惰性抓取的情况下访问字段之前创建一个代理。因此,只要习惯于正确操作,您就不会不幸发现问题。全部移动那些作为属性级访问的getter注释不需要代理

字段级变量应该是私有的

你在那里把一个整数转换成一个整数…有些东西让我不想看它,老实说,可能会有一点愚蠢的懒惰,最终成为你的问题

当您使用新的HashSet(0)时,请继续初始化该集;类似的事情。仍然会更新我们。

更改此项:

@OneToMany(mappedBy = "providertype")
private Set<HL7DocumentEntity> documententities;
更改为:

@ManyToOne(fetch = FetchType.LAZY)
  @JoinTable(name = "Link_Documents", joinColumns = {@JoinColumn(name = "change_this_with_primary_key_variable_name_from_HL7DocumentEntity")}, inverseJoinColumns = {@JoinColumn(name = "codePk")})
  private HL7GeneralCode providertype;
我认为您必须将“使用\u primary\u key\u variable\u name\u from\u HL7DocumentEntity”更改为“id”,就像在BaseEntity中一样,但看看您的sql表,您将看到正确的名称

我希望您注意到我是如何告诉JPA使用相同的“Link_Documents”表来链接这两个表的。我认为这是您的错误所在。请确保使用正确的变量名更改我告诉您的位置,我认为应该可以更改此项:

@OneToMany(mappedBy = "providertype")
private Set<HL7DocumentEntity> documententities;
更改为:

@ManyToOne(fetch = FetchType.LAZY)
  @JoinTable(name = "Link_Documents", joinColumns = {@JoinColumn(name = "change_this_with_primary_key_variable_name_from_HL7DocumentEntity")}, inverseJoinColumns = {@JoinColumn(name = "codePk")})
  private HL7GeneralCode providertype;
我认为您必须将“使用主关键字更改此变量名称”更改为“id”,就像在BaseEntity中一样,但要使用l