简体   繁体   中英

Java JPA OneToMany relation and query

maybe duplicate question but I couldn't fina a solution for my case which I think is pretty simple.

I have two tables like so:

在此处输入图像描述

And those are the related DTO Object:

First table

@Entity
@Table(name = "DA10003_REF_SIGNALEMENT")
public class RefSignalement {

    @Id
    @Column(name = "CD_SIGNALEMENT")
    public String codeSignalement;

    @Column(name = "LIBELLE")
    public String libelle;

    @Column(name = "CATEGORIE")
    public String categorie;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "CD_SIGNALEMENT")
    public List<RefMessage> refMessages;
}

Second table:

@Entity
@Table(name = "DA10004_REF_MESSAGE")
public class RefMessage {

    @Id
    @Column(name = "CD_SIGNALEMENT")
    public String codeSignalement;

    @Id
    @Column(name = "DESTINATAIRE")
    public String destinataires;

    @Column(name = "MESSAGE")
    public String message;
}

And the following query to get all the RefSignelement with the associated message:

List<RefSignalement> listRefSignalement = em.createQuery("SELECT p FROM RefSignalement p, RefMessage m", RefSignalement.class).getResultList();

Unfortunately it's returning an empty list, I have tried to change it with join fetch but nothing change.

Thank for the help

Remember that in JPQL you have to think in Objects, not relations. You want to fetch all 'RefSignalement' and eagerly fetch their 'refMessages' properties:

SELECT DISTINCT s FROM RefSignalement s JOIN FETCH s.refMessages

Here the "distinct" is only needed by JPA when assembling your resulting entities, but add unnecessary overhead to the SQL Query. If you have a Hibernate version >= 5.2.2 (I think), then there is a query hint you can use to avoid that:

List<RefSignalement> sigs = entityManager
.createQuery(
    "select distinct s " +
    "from RefSignalement s " +
    "left join fetch s.refMessages ")
.setHint("hibernate.query.passDistinctThrough", false)
.getResultList();

Read more about it here .

a couple of things, RefMessage class is using composite primary key so i guess you need to use @IdClass or @EmbeddedId annotation. here I'm providing using @IdClass

public class RefId implements Serializable {

private String codeSignalement;

private String destinataires;

// default constructor


public RefId() {
}

public RefId(String codeSignalement, String destinataires) {
    this.codeSignalement = codeSignalement;
    this.destinataires = destinataires;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    RefId refId = (RefId) o;
    return Objects.equals(codeSignalement, refId.codeSignalement) &&
            Objects.equals(destinataires, refId.destinataires);
}

@Override
public int hashCode() {
    return Objects.hash(codeSignalement, destinataires);
}
}

then you need to use like follows

@Entity
@Table(name = "DA10004_REF_MESSAGE")
@IdClass(RefId.class)
public class RefMessage   {

@Id
@Column(name = "CD_SIGNALEMENT")
public String codeSignalement;

@Id
@Column(name = "DESTINATAIRE")
public String destinataires;

@Column(name = "MESSAGE")
public String message;
} 

define your repository as follows:

public interface RefSignalementRepo  extends 
JpaRepository<RefSignalement, String> {
}

RefSignalement class defination as follows:

@Entity
@Table(name = "DA10003_REF_SIGNALEMENT")
public class RefSignalement {

@Id
@Column(name = "CD_SIGNALEMENT")
public String codeSignalement;

@Column(name = "LIBELLE")
public String libelle;

@Column(name = "CATEGORIE")
public String categorie;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JoinColumn(name = "CD_SIGNALEMENT")
public List<RefMessage> refMessages;
}

very example app

@SpringBootApplication
public class App {

public static void main(String[] args) {
    ConfigurableApplicationContext context = 
   SpringApplication.run(App.class, args);


    RefSignalementRepo repo = context.getBean(RefSignalementRepo.class);

    RefSignalement obj = new RefSignalement();
    obj.codeSignalement = "1";

    obj = repo.save(obj);

    obj.refMessages = new ArrayList<>();

    RefMessage message = new RefMessage();
    message.codeSignalement = "1";
    message.destinataires = "2";
    message.message = "custom message";

    obj.refMessages.add(message);

    obj = repo.save(obj);

    List<RefSignalement> objs = repo.findAll();

    System.out.println(objs.get(0).refMessages.size());


    EntityManager em = context.getBean(EntityManager.class);

    List<RefSignalement> listRefSignalement = em.createQuery("SELECT p FROM RefSignalement p, RefMessage m", RefSignalement.class).getResultList();


    System.out.println(listRefSignalement.get(0).refMessages.size());

}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM