Java Отношение и запрос JPA OneToMany - PullRequest
0 голосов
/ 18 июня 2020

может быть дублированный вопрос, но я не смог найти решение для моего случая, которое, на мой взгляд, довольно простое.

У меня есть две такие таблицы:

enter image description here

И это связанный объект DTO:

Первая таблица

@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;
}

Вторая таблица:

@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;
}

И следующий запрос к получить все RefSignelement с соответствующим сообщением:

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

К сожалению, он возвращает пустой список, я пытался изменить его с помощью join fetch, но ничего не изменилось.

Спасибо за помощь

Ответы [ 2 ]

1 голос
/ 18 июня 2020

пара вещей, RefMessage класс использует составной первичный ключ, поэтому я думаю, вам нужно использовать аннотацию @IdClass или @EmbeddedId. здесь я использую @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);
}
}

, тогда вам нужно использовать следующее:

@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;
} 

определите свой репозиторий следующим образом:

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

RefSignalement определение класса следующим образом:

@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;
}

пример приложения

@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());

}
}
1 голос
/ 18 июня 2020

Помните, что в JPQL вы должны мыслить объектами, а не отношениями. Вы хотите получить все 'RefSignalement' и с нетерпением получить их свойства 'refMessages':

SELECT DISTINCT s FROM RefSignalement s JOIN FETCH s.refMessages

Здесь «отдельный» нужен только JPA при сборке ваших результирующих сущностей, но добавляет ненужные накладные расходы к SQL Запрос. Если у вас версия Hibernate> = 5.2.2 (я думаю), тогда есть подсказка запроса, которую вы можете использовать, чтобы избежать этого:

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

Подробнее об этом здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...