Java 防止休眠在保存父对象时自动删除@Transient子对象

Java 防止休眠在保存父对象时自动删除@Transient子对象,java,hibernate,spring-data-jpa,hibernate-mapping,Java,Hibernate,Spring Data Jpa,Hibernate Mapping,在SpringJPA中,我将一个childs列表声明为@Transient,我不想将其保留在parent中。问题是,当我保存其父项时,hibernate删除了child列表。例如: @RunWith(SpringRunner.class) @DataJpaTest public class JPAUnitTest { @Autowired TutorialRepository repository; @Test public void paymentsShouldExistA

在SpringJPA中,我将一个childs列表声明为@Transient,我不想将其保留在parent中。问题是,当我保存其父项时,hibernate删除了child列表。例如:

@RunWith(SpringRunner.class)
@DataJpaTest
public class JPAUnitTest {

  @Autowired
  TutorialRepository repository;

  @Test
  public void paymentsShouldExistAfterSaved() {
      
    Tutorial tutorial = new Tutorial("Tut title", "Tut desc", true);
    tutorial.addStudent(new Student("John"));
    
    long id = repository.save(tutorial).getId();
    Tutorial found = repository.findById(id).get();
    
    org.junit.Assert.assertEquals("John", found.getStudents().get(0).getName());
    
    found.getStudents().clear();
    
    Student s = new Student("Kelly");
    s.addPayment(100, LocalDate.of(2020, 11, 9));
    s.addPayment(550, LocalDate.of(2020, 12, 18));  
    s.addPayment(80, LocalDate.of(2020, 12, 29));   

    found.addStudent(s);    
    org.junit.Assert.assertEquals(3, found.getStudents().get(0).getPayments().size());
    
    repository.save(found);

    org.junit.Assert.assertEquals("Kelly", found.getStudents().get(0).getName());
    //Error -  expected:3 but was:0
    org.junit.Assert.assertEquals(3, found.getStudents().get(0).getPayments().size());

  }  
  
在上面的测试中,最后一个断言失败了,因为付款在测试结束后就消失了。付款对象为学生班级的子女:

@Entity
@Table(name = "payments")
public class Payment {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "amount")
    private double amount;
    
    @Column(name = "payment_date")
    private LocalDate date;
    
    public Payment() {}

    public Payment(double amount, LocalDate date) {
        this.amount = amount;
        this.date = date;
    }
}


@Entity
@Table(name = "students")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "name")
    private String name;
    
    @ManyToOne(fetch = FetchType.EAGER)
    private Tutorial tutorial;
    
    @Transient
    private List<Payment> payments = new ArrayList<>();
    
    public Student() {}

    public Student(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }

    public List<Payment> getPayments() {
        return payments;
    }

    public void addPayment(double amount, LocalDate date) {
        this.payments.add(new Payment(amount, date));
    }
}


@Entity
@Table(name = "tutorials")
public class Tutorial {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "title")
    private String title;

    @Column(name = "description")
    private String description;

    @Column(name = "published")
    private boolean published;
    
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "tutorial")
    private List<Student> students = new ArrayList<>();

    public Tutorial() {}

    public Tutorial(String title, String description, boolean published) {
        this.title = title;
        this.description = description;
        this.published = published;
    }
    
    public void addStudent(Student student) {
        this.students.add(student);
    }
    
    
    public List<Student> getStudents() {
        return students;
    }

    public long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public boolean isPublished() {
        return published;
    }

    public void setPublished(boolean isPublished) {
        this.published = isPublished;
    }
}
@实体
@表(name=“付款”)
公共类支付{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(name=“amount”)
私人双倍金额;
@列(name=“付款日期”)
私有本地日期;
公共支付(){}
公共支付(双倍金额,本地日期){
这个。金额=金额;
this.date=日期;
}
}
@实体
@表(name=“学生”)
公立班学生{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(name=“name”)
私有字符串名称;
@manytone(fetch=FetchType.EAGER)
私人辅导;
@短暂的
私有列表付款=新建ArrayList();
公立学生(){}
公立学生(字符串名称){
this.name=名称;
}
公共字符串getName(){
返回名称;
}
公共列表getPayments(){
归还款项;
}
公共作废付款(双倍金额,本地日期){
此.payments.add(新付款(金额、日期));
}
}
@实体
@表(name=“教程”)
公开课辅导{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(name=“title”)
私有字符串标题;
@列(name=“description”)
私有字符串描述;
@列(name=“published”)
私有布尔出版;
@OneToMany(cascade=CascadeType.ALL,orphanRemoving=true,fetch=FetchType.EAGER,mappedBy=“tutorial”)
private List students=new ArrayList();
公共教程(){}
公共教程(字符串标题、字符串描述、布尔值发布){
this.title=标题;
this.description=描述;
this.published=published;
}
公立学校学生(学生){
this.student.add(student);
}
公众学生名单{
留学生;
}
公共长getId(){
返回id;
}
公共字符串getTitle(){
返回标题;
}
公共无效集合标题(字符串标题){
this.title=标题;
}
公共字符串getDescription(){
返回说明;
}
公共void集合描述(字符串描述){
this.description=描述;
}
公共布尔值isPublished(){
公布报税表;
}
public void setPublished(布尔值isPublished){
this.published=isPublished;
}
}
我的版本:
弹簧靴2.2

Java 1.8

这个问题可能与DataJpaTest有关,在保存数据后,如果它是持久的,则刷新所有字段,如果不是,则分配空值。你可以用一个真实的容器试试,我想它会正常工作。

不。我首先遇到了真实容器的问题,然后我创建了这个测试来证明它。2017年询问并回答:@Gregg如果可以,请在回答中详细说明。我理解@Transient值是如何在db端丢失的。java端字段在其持久化之前是否已删除?为什么它会影响java中的
found
对象?save()返回持久化的值,但它看起来不像是被提取到变量中。