我正在使用hibernate来处理数据库事务。
我有2个实体:
SegmentFileEntity
SegmentFileMappingEntity
SegmentFileEntity可以有一个或多个SegmentFileMappingEntity。 Join键是SEGMENT_FILE_ID,它是
中的主键SegmentFileEntity的相关表格结构:
CREATE TABLE OAP_META_NEW.SEGMENT_FILE
(
SEGMENT_FILE_ID NUMBER(10) DEFAULT OAP_META_NEW.SEGMENT_FILE_SEQ.NEXTVAL CONSTRAINT SEGMENTFILEID_NOTNULL NOT NULL,
SEGMENT_FILE_PATH VARCHAR2(500 BYTE) CONSTRAINT SEGMENTFILEPATH_NOTNULL NOT NULL,
CLIENT_ID NUMBER(10) CONSTRAINT SEGMENTFILE_CLIENTID_NOTNULL NOT NULL,
INSERT_DATE DATE NOT NULL
)
该表上的约束细节:
[![在此处输入图像说明] [1]] [1]
SegmentFileMappingEntity的相关表格结构:
CREATE TABLE OAP_META_NEW.SEGMENT_FILE_MAPPING
(
SEGMENT_FILE_MAPPING_ID NUMBER(10) DEFAULT OAP_META_NEW.SEGMENT_FILE_MAPPING_SEQ.NEXTVAL CONSTRAINT SFM_SFMID_NOTNULL NOT NULL,
SEGMENT_FILE_ID NUMBER(10) CONSTRAINT SFM_SEGMENTFILEID_NOTNULL NOT NULL,
ATTRIBUTE_POSITION NUMBER(3) CONSTRAINT SFM_ATTRIBUTEPOSITION_NOTNULL NOT NULL,
ATTRIBUTE_NAME VARCHAR2(100 BYTE) CONSTRAINT SFM_ATTRIBUTENAME_NOTNULL NOT NULL
)
该表上约束的细节:
[![在此处输入图像说明] [2]] [2]
以下是我在这些实体上运行的测试:
public class SegmentFileTest
extends AbstractTest
{
private long attCatId;
private int attCatTypeId;
private long attDelimitedSavedId;
private long attFixedSavedId;
private long attDerivedSavedId;
SegmentFileService segmentFileService;
@BeforeClass
public void setUpAttributeCategoryTypeAttributeCategory()
{
segmentFileService = context.getBean( SegmentFileService.class );
}
@Test
public void saveSegmentFile()
{
//Create segment-file
SegmentFileEntity segmentFile = new SegmentFileEntity();
segmentFile.setClientId( 0 );
segmentFile.setSegmentFilePath( "/fakepath/" );
segmentFile.setInsertDate( new Date((new java.util.Date()).getTime()));
//Create segment-file-mapping
List<SegmentFileMappingEntity> fileMappings = new ArrayList<SegmentFileMappingEntity>( );
SegmentFileMappingEntity segmentFileMapping1 = new SegmentFileMappingEntity();
segmentFileMapping1.setAttributeName( "attr1" );
segmentFileMapping1.setAttributePosition( 1 );
SegmentFileMappingEntity segmentFileMapping2 = new SegmentFileMappingEntity();
segmentFileMapping2.setAttributeName( "attr2" );
segmentFileMapping2.setAttributePosition( 2 );
fileMappings.add(segmentFileMapping1);
fileMappings.add(segmentFileMapping2);
segmentFile.setSegmentFileAttributeMappings( fileMappings );
segmentFileService.saveSegmentFileEntity( segmentFile );
}
}
问题:
如果我在保存SegmentFileEntity时只使用1个SegmentFileMappingEntity,那很好。但如果我使用超过1个SegmentFileMappingEntity,同时保存SegmentFileEntity,我看到错误:
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session. Any insight?
以下是我的java-hibernate实体:
** SegmentFileEntity:**
package com.company.online.segment.api.entities;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Date;
import java.util.Collection;
import java.util.List;
@Entity
@Table( name = "SEGMENT_FILE", schema = "OAP_META_NEW" )
@SequenceGenerator( name = "segment_file_seq", sequenceName = "OAP_META_NEW.SEGMENT_FILE_SEQ" )
public class SegmentFileEntity implements Serializable
{
private int segmentFileId;
private String segmentFilePath;
private int clientId;
private Date insertDate;
@Id
@Column( name = "SEGMENT_FILE_ID" , nullable = false, unique = true, precision = 0 )
@GeneratedValue( strategy = GenerationType.AUTO, generator = "segment_file_seq" )
@JoinColumn(name = "SEGMENT_FILE_ID", referencedColumnName = "SEGMENT_FILE_ID")
public int getSegmentFileId()
{
return segmentFileId;
}
public void setSegmentFileId( int segmentFileId )
{
this.segmentFileId = segmentFileId;
}
@Basic @Column( name = "SEGMENT_FILE_PATH" ) public String getSegmentFilePath()
{
return segmentFilePath;
}
public void setSegmentFilePath( String segmentFilePath )
{
this.segmentFilePath = segmentFilePath;
}
@Basic @Column( name = "CLIENT_ID" ) public int getClientId()
{
return clientId;
}
public void setClientId( int clientId )
{
this.clientId = clientId;
}
@Basic @Column( name = "INSERT_DATE" )
public Date getInsertDate()
{
return insertDate;
}
public void setInsertDate( Date insertDate )
{
this.insertDate = insertDate;
}
@Override public boolean equals( Object o )
{
if ( this == o )
return true;
if ( o == null || getClass() != o.getClass() )
return false;
SegmentFileEntity that = (SegmentFileEntity) o;
if ( segmentFileId != that.segmentFileId )
return false;
if ( clientId != that.clientId )
return false;
if ( segmentFilePath != null ? !segmentFilePath.equals( that.segmentFilePath ) : that.segmentFilePath != null )
return false;
if ( insertDate != null ? !insertDate.equals( that.insertDate ) : that.insertDate != null )
return false;
return true;
}
@Override public int hashCode()
{
int result = segmentFileId;
result = 31 * result + ( segmentFilePath != null ? segmentFilePath.hashCode() : 0 );
result = 31 * result + clientId;
result = 31 * result + ( insertDate != null ? insertDate.hashCode() : 0 );
return result;
}
private List<SegmentFileMappingEntity> segmentFileAttributeMappings;
@OneToMany( cascade = CascadeType.ALL, fetch = FetchType.EAGER , orphanRemoval = true )
@JoinColumn( name = "SEGMENT_FILE_ID", referencedColumnName = "SEGMENT_FILE_ID", nullable = false)
public List<SegmentFileMappingEntity> getSegmentFileAttributeMappings()
{
return segmentFileAttributeMappings;
}
public void setSegmentFileAttributeMappings( List<SegmentFileMappingEntity> segmentFileAttributeMappings )
{
this.segmentFileAttributeMappings = segmentFileAttributeMappings;
}
}
SegmentFileMappingEntity:
package com.company.online.segment.api.entities;
import javax.persistence.*;
import java.io.Serializable;
@Entity @Table( name = "SEGMENT_FILE_MAPPING", schema = "OAP_META_NEW" )
public class SegmentFileMappingEntity implements Serializable
{
private int segmentFileMappingId;
private int segmentFileId;
private int attributePosition;
private String attributeName;
@Id @Column( name = "SEGMENT_FILE_MAPPING_ID" ) public int getSegmentFileMappingId()
{
return segmentFileMappingId;
}
public void setSegmentFileMappingId( int segmentFileMappingId )
{
this.segmentFileMappingId = segmentFileMappingId;
}
@Basic
@Column( name = "SEGMENT_FILE_ID", nullable = false, precision = 0, updatable = false, insertable = false )
public int getSegmentFileId()
{
return segmentFileId;
}
public void setSegmentFileId( int segmentFileId )
{
this.segmentFileId = segmentFileId;
}
@Basic @Column( name = "ATTRIBUTE_POSITION" ) public int getAttributePosition()
{
return attributePosition;
}
public void setAttributePosition( int attributePosition )
{
this.attributePosition = attributePosition;
}
@Basic @Column( name = "ATTRIBUTE_NAME" ) public String getAttributeName()
{
return attributeName;
}
public void setAttributeName( String attributeName )
{
this.attributeName = attributeName;
}
@Override public boolean equals( Object o )
{
if ( this == o )
return true;
if ( o == null || getClass() != o.getClass() )
return false;
SegmentFileMappingEntity that = (SegmentFileMappingEntity) o;
if ( segmentFileMappingId != that.segmentFileMappingId )
return false;
if ( segmentFileId != that.segmentFileId )
return false;
if ( attributePosition != that.attributePosition )
return false;
if ( attributeName != null ? !attributeName.equals( that.attributeName ) : that.attributeName != null )
return false;
return true;
}
@Override public int hashCode()
{
int result = segmentFileMappingId;
result = 31 * result + segmentFileId;
result = 31 * result + attributePosition;
result = 31 * result + ( attributeName != null ? attributeName.hashCode() : 0 );
return result;
}
}
答案 0 :(得分:1)
在SegmentFileMappingEntity
中,您使用segmentFileMappingId
为字段@Id
注释了访问者,因此hibernate会将其用作数据库标识符。这意味着它必须对每个对象行都是唯一的。
但你没有为它提供价值。
因此它是一个整数,它的默认值是0,因此在创建对象期间,每个创建的SegmentFileMappingEntity
实例都会获得0作为标识符。在您当前的会话/持久性上下文中,这是&#34;意外确定&#34;对于一个条目,不可能保存第二个。
解决方案是为应用程序级别的每个实例生成唯一值,或者让hibernate为您生成一个(就像您已经使用SegmentFileEntity
访问者getSegmentFileId()
的数据库序列一样)。
有关详细信息,请参阅here。