JPA 一对多关系无法正常工作

问题描述 投票:0回答:2

我对 Membre 和 Sortie 之间的关系有疑问,但我不知道我做错了什么。每次我运行测试时都会触发异常。

有人可以帮我吗?

Membre.java

@Entity(name = "Membre")
@Data
@NoArgsConstructor
@AllArgsConstructor

public class Membre implements Serializable {

    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long idMembre ;
    
    @Basic(optional = false)
    private String nomMembre ;
    
    @Basic(optional = false)
    private String prenomMembre ;
    
    @Basic(optional = false)
    private String adresseElectronique ; 
    
    //Il est plus sure d'utiliser un char[] plutot qu'un String pour un mot de passe 
    @Basic(optional = false)
    private char[] motDePasse ;
    
    @Version
    private long versionMembre = 0 ;
    
    public Membre(String nom, String prenom, String email, char[] mdp, Set<Sortie> sorties){
        this(0, nom, prenom, email, mdp, 0, sorties);
    }
    
    @OneToMany(fetch = FetchType.LAZY,
            mappedBy = "createurSortie",
            cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE })
    @ToString.Exclude
    @OrderBy("idSortie asc")
    private Set<Sortie> sortiesMembre ;
    
    public void addSortie(Sortie s) {
        if (sortiesMembre == null) {
            sortiesMembre = new HashSet<>();
        }
        sortiesMembre.add(s);
        s.setCreateurSortie(this);
    }
    
    @PreUpdate
    public void beforeUpdate() {
        System.err.println("PreUpdate␣of␣" + this);
    }
    @PostUpdate
    public void afterUpdate() {
        System.err.println("PostUpdate␣of␣" + this);
    }
}

Sortie.java

@Entity(name = "Sortie")
@Data
@NoArgsConstructor
@AllArgsConstructor
@NamedQuery(
        name="findSortiesByCriteria",
        query="SELECT s FROM Sortie s WHERE s.descriptionSortie LIKE :pattern"
)
public class Sortie implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long idSortie ;
    
    @Basic
    private String nomSortie ;
    
    @Basic
    private String descriptionSortie ;
    
    @Basic
    private URL siteWebSortie ;
    
    @Basic
    @Temporal(TemporalType.DATE)
    private Date dateSortie ;
    
    @Version
    private long versionSortie = 0 ;
    
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    @JoinColumn(name = "idMembre")
    @ToString.Exclude
    private Membre createurSortie;
    
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    @ToString.Exclude
    private Categorie categorie ;
    
    public Sortie(String nomSortie, String descriptionSortie, URL siteWebSortie, Date dateSortie,Membre createurSortie,Categorie categorie) {
        this(0, nomSortie, descriptionSortie, siteWebSortie, dateSortie, 0, createurSortie, categorie);
    }
    
    @PreUpdate
    public void beforeUpdate() {
    System.err.println("PreUpdate␣of␣" + this);
    }
    @PostUpdate
    public void afterUpdate() {
    System.err.println("PostUpdate␣of␣" + this);
    }

}

我的测试

    @Test
    public void testGetMembreAndSorties() {
        var membre = new Membre("Katon","Den","[email protected]",new char[] {'j', 'j'},null);
        
        dao.addMember(membre);

        var sortie1 = new Sortie("Sortie à la montagne", "Une sortie dans la montagne.", null, null, null, null);
        
        dao.addSortie(sortie1);
        
        membre.addSortie(sortie1);
        
        Membre foundMember = dao.findMember(membre.getIdMembre());
        assertEquals(1,foundMember.getSortiesMembre().size());

        dao.removeMember(foundMember.getIdMembre());
        dao.removeSortie(sortie1.getIdSortie());
    }

例外情况 org.opentest4j.AssertionFailedError:预期:<1>但是是:<0>

这意味着我添加到会员中的出击没有被存储。

java spring-boot oop debugging jpa
2个回答
0
投票

它没有被存储,因为你在 dao 中保存实体后调用

membre.addSortie

另外,我不建议您对实体使用

@Data
,它可能会导致意外行为(更多详细信息请参见此处https://jpa-buddy.com/blog/lombok-and-jpa-what-may-出错/


0
投票
  • 删除@Data并在必要时使用@Getter和@Setter。
    • 双向关联中@EqualsAndHashCode导致StackOverFlow无限引用问题
  • 删除@Data并用@Getter和@Setter替换后,我编写了以下测试。
    • 我通过了测试并按预期检查了日志。
@SpringBootTest
public class ExampleTest {

    @Autowired
    EntityManagerFactory emf;

    @Test
    void testGetMembreAndSorties() {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        var membre = new Membre("Katon", "Den", "[email protected]", new char[]{'j', 'j'}, null);
        em.persist(membre);

        var sortie1 = new Sortie("Sortie à la montagne", "Une sortie dans la montagne.", null, null, null);
        em.persist(sortie1);

        membre.addSortie(sortie1);

        Membre foundMember = em.find(Membre.class, membre.getIdMembre());
        tx.commit();
        assertEquals(1, foundMember.getSortiesMembre().size());
    }
}

日志

Hibernate: select next value for membre_seq
Hibernate: select next value for sortie_seq
PreUpdate␣of␣com.example.demo.domain.Membre@5b3f0552
PreUpdate␣of␣com.example.demo.domain.Sortie@708f4d81
Hibernate: insert into membre (adresse_electronique,mot_de_passe,nom_membre,prenom_membre,version_membre,id_membre) values (?,?,?,?,?,?)
Hibernate: insert into sortie (id_membre,date_sortie,description_sortie,nom_sortie,site_web_sortie,version_sortie,id_sortie) values (?,?,?,?,?,?,?)
PostUpdate␣of␣com.example.demo.domain.Membre@5b3f0552
Hibernate: update sortie set id_membre=?,date_sortie=?,description_sortie=?,nom_sortie=?,site_web_sortie=?,version_sortie=? where id_sortie=? and version_sortie=?
PostUpdate␣of␣com.example.demo.domain.Sortie@708f4d81

预计您代码的 DAO 中的某些内容会导致问题。

希望对您有所帮助。 :)

© www.soinside.com 2019 - 2024. All rights reserved.