我试图运行UT,但在@Before方法上失败了。这就是错误:
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "UK_PBNJJ4MCIQ51S0SJV9U3J2WQ4_INDEX_5 ON PUBLIC.XACTIVITYCONTENTTYPE(CONTENTTYPE_ID) VALUES (19, 1)"; SQL statement:
insert into XACTIVITYCONTENTTYPE (ACTIVITY_ID, CONTENTTYPE_ID) values (?, ?) [23505-197]
我有一个对象数组(ActivityEntity(,我正在初始化它并将其保存在H2 DB:中
for (int i = 0; i < activities.length; i++) {
Date createdDate = new Date();
ActivityEntity activity = new ActivityEntity();
activity.setType(ActivityType.valueOf(properties.getType()));
activity.setLabel(ActivityLabel.valueOf(properties.getLabel()));
activity.setStatus(Status.valueOf(properties.getStatus()));
activity.setDeliveryType(DeliveryType.valueOf(properties.getDeliveryType()));
activity.setSubject(em.find(SubjectEntity.class, subjectId));
activity.setFontSize(FontSize.valueOf(properties.getFontSize()));
activity.setEstimatedTime(ESTIMATED_TIME);
activity.setPlannedTime(properties.getPlannedTime());
activity.setInteractivityType(InteractivityType.valueOf(properties.getInteractivityType()));
activity.setAudience(Audience.valueOf(properties.getAudience()));
activity.setPurpose(Purpose.valueOf(properties.getPurpose()));
activity.setAcademicLevel(AcademicLevel.valueOf(properties.getAcademicLevel()));
activity.setEnvironment(Environment.valueOf(properties.getEnvironment()));
activity.setInstructionMethod(InstructionMethod.valueOf(properties.getInstructionMethod()));
activity.setCreatedBy(CREATED_BY);
activity.setCreatedDate(createdDate);
activity.setModifiedBy(CREATED_BY);
activity.setModifiedDate(createdDate);
activity.setDeprecated(properties.isDeprecated());
activity.setTemplate(properties.isTemplate());
activity.setCurriculumProvider(CurriculumProvider.valueOf(properties.getCurriculumProvider()));
activity.setShowLessonNavigator(properties.isShowLessonNavigator());
activity.setShowHeader(properties.isShowHeader());
activity.setDisplayModuleType(properties.isDisplayModuleType());
activity.setDisplayLabelType(properties.isDisplayLabelType());
activity.setShowFooter(properties.isShowFooter());
activity.setShowPagination(properties.isShowPagination());
activity.setDisplayProgressBar(properties.isDisplayProgressBar());
activity.setDisplayResources(properties.isDisplayResources());
activity.setLanguage(language);
activity.setPrimaryStatus(PrimaryStatus.valueOf(properties.getPrimaryStatus()));
activity.setIntendedDeliveryType(IntendedDeliveryType.valueOf(properties.getIntendedDeliveryType()));
activity.setNextGen(properties.isNextGen());
activity.setExcludeFromSearch(properties.isExcludeFromSearch());
activity.setExcludeFromRecommender(properties.isExcludeFromRecommender());
activity.setTeacherCreated(properties.isTeacherCreated());
activity.setTitle(TITLE + (i + 1), language);
activity.getGrades().addAll(grades);
activity.getStudentGroupings().add(new StudentGroupingEntity(properties.getStudentGroupingId()));
activity.getPedagogicalIntents().add(new PedagogicalIntentEntity(properties.getPedagogicalIntentId()));
activity.getLearnerTypes().add(new LearnerTypeEntity(properties.getLearnerTypeId()));
activity.getContentTypes().add(new ContentTypeEntity(properties.getContentTypeId()));
activities[i] = em.persist(activity);
}
em.flush();
最后一个集合是与错误相关的属性。属性的ContentTypeId值为19。现在,这是活动实体类的一部分:
@Entity
@Table(name = "ACTIVITY")
public class ActivityEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_ACTIVITY_ACTIVITY_ID")
@SequenceGenerator(name = "SQ_ACTIVITY_ACTIVITY_ID", sequenceName = "SQ_ACTIVITY_ACTIVITY_ID", allocationSize = 1)
@Column(name = "ACTIVITY_ID")
private Integer id;
//MORE FIELDS LEFT OUT FOR CLARITY
@ManyToMany
@JoinTable(name = "XACTIVITYCONTENTTYPE", joinColumns = { @JoinColumn(name = "ACTIVITY_ID", referencedColumnName = "ACTIVITY_ID") }, inverseJoinColumns = { @JoinColumn(name = "CONTENTTYPE_ID", referencedColumnName="ID") } )
private List<ContentTypeEntity> contentTypes = new ArrayList<>();
}
这是ContentTypeEntity类:
@Entity
@Table(name = "CONTENTTYPE")
public class ContentTypeEntity {
@Id
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@Column(name = "SEQ_NUM")
private int seqNum;
public ContentTypeEntity() {
}
public ContentTypeEntity(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSeqNum() {
return seqNum;
}
public void setSeqNum(int seqNum) {
this.seqNum = seqNum;
}
}
如果我进行调试,那么ActivityEntity的id将为我放入数组中的3个对象中的每一个正确生成(ids=[1,2,3](。所以我不明白为什么第二个插入使用id=1,这就是异常的含义。如果我在数组中放入一个ActivityEntity,则一切正常。
您还没有粘贴所有的代码,也无法分配em.persist的返回类型,但我认为问题可能与创建多个id为19的contenttype实例有关。
假设id为19的内容类型已经被持久化,并且您正试图只创建对它的引用,而不是持久化它,因为您的ManyToMany中没有级联。您可以像下面的示例测试代码所示那样做。交易在那里,因为我不知道你代码中的tx边界,只是为了单独保存内容类型
@Test
public void saveActivities() {
// Tx1 - Persist content type
EntityTransaction tx1 = em.getTransaction();
tx1.begin();
ContentTypeEntity contentType = new ContentTypeEntity(19);
em.persist(new ContentTypeEntity(19));
tx1.commit();
em.detach(contentType);
// Tx2 - Persist activities using a reference to content type
EntityTransaction tx2 = em.getTransaction();
tx2.begin();
for (int i = 0; i < 3; i++) {
ActivityEntity activity = new ActivityEntity();
activity.getContentTypes().add(em.getReference(ContentTypeEntity.class, 19));
em.persist(activity);
}
tx2.commit();
// assertions
}