我在数据库里有个协会-
我想把数据保存在这样的表格里-
相应的JPA实体已经以这种方式建模(为了简单起见,省略了getters/setter)-
学生实体-
@Entity
@Table(name = "student")
public class Student {
@Id
@SequenceGenerator(name = "student_pk_generator", sequenceName =
"student_pk_sequence", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"student_pk_generator")
@Column(name = "student_id", nullable = false)
private Long studentId;
@Column(name = "name", nullable = false)
private String studentName;
@OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
private Set<StudentSubscription> studentSubscription;
}
STUDENT_SUBSCRIPTION实体-
@Entity
@Table(name = "student_subscription")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class StudentSubscription {
@Id
private Long studentId;
@ManyToOne(optional = false)
@JoinColumn(name = "student_id", referencedColumnName = "student_id")
@MapsId
private Student student;
@Column(name = "valid_from")
private Date validFrom;
@Column(name = "valid_to")
private Date validTo;
}
LIBRARY_SUBSCRIPTION实体-
@Entity
@Table(name = "library_subscription",
uniqueConstraints = {@UniqueConstraint(columnNames = {"library_code"})})
@PrimaryKeyJoinColumn(name = "student_id")
public class LibrarySubscription extends StudentSubscription {
@Column(name = "library_code", nullable = false)
private String libraryCode;
@PrePersist
private void generateLibraryCode() {
this.libraryCode = // some logic to generate unique libraryCode
}
}
COURSE_SUBSCRIPTION实体-
@Entity
@Table(name = "course_subscription",
uniqueConstraints = {@UniqueConstraint(columnNames = {"course_code"})})
@PrimaryKeyJoinColumn(name = "student_id")
public class CourseSubscription extends StudentSubscription {
@Column(name = "course_code", nullable = false)
private String courseCode;
@PrePersist
private void generateCourseCode() {
this.courseCode = // some logic to generate unique courseCode
}
}
现在,有一个学生实体已经持久化了id,比方说- 100。现在我想坚持这个学生的图书馆订阅。为此,我使用Spring存储库创建了一个简单的测试-
@Test
public void testLibrarySubscriptionPersist() {
Student student = studentRepository.findById(100L).get();
StudentSubscription librarySubscription = new LibrarySubscription();
librarySubscription.setValidFrom(//some date);
librarySubscription.setValidTo(//some date);
librarySubscription.setStudent(student);
studentSubscriptionRepository.save(librarySubscription);
}
在运行这个测试的时候,我得到了异常-
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.springboot.data.jpa.entity.Student; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.springboot.data.jpa.entity.Student
为了解决这个问题,我在测试中附加了一个@Transactional。这修正了分离实体的上述异常,但是实体StudentSubscription和LibrarySubscription不会被持久化到DB。事实上,事务正在回滚。
把这个异常记录在日志里-
INFO 3515 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@35390ee3 testClass = SpringDataJpaApplicationTests, testInstance = com.springboot.data.jpa.SpringDataJpaApplicationTests@48a12036, testMethod = testLibrarySubscriptionPersist@SpringDataJpaApplicationTests, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5e01a982 testClass = SpringDataJpaApplicationTests, locations = '{}', classes = '{class com.springboot.data.jpa.SpringDataJpaApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@18ece7f4, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@264f218, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@2462cb01, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@928763c, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@7c3fdb62, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@1ad282e0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]
现在我有几个问题-
我试过很多东西,但没有运气。向JPA和Spring数据专家寻求帮助:-)
提前谢谢。
发布于 2022-11-15 08:07:44
事务正在回滚,因为测试正在测试方法中执行DB更新。如果事务包含任何更新DB,事务将自动回滚。这里还有使用事务的强制要求,因为只要获取了EntityManager实体,就会关闭它,因此要保持该打开状态,测试必须在事务上下文中。
如果我在我的测试用例中使用了testDB,那么spring可能就不会回滚这个更新了。
将设置一个H2 testDb并在那里执行相同的操作,并发布结果。
谢谢你们的快速帮助。:-)
https://stackoverflow.com/questions/74411600
复制相似问题