Java JPA LazyInitializationException при попытке создать новый объект и добавить его в Arraylist - PullRequest
0 голосов
/ 10 ноября 2019

У меня есть приложение Java Spring JPA, которое имеет сущность Bord и сущность BordRow. A Bord имеет несколько BordRows. Теперь я попытался создать новый BordRow и добавить его в список BordRows в Bord. Тем не менее, я получаю LazyInitializationException. Как мне изменить мой код, чтобы создать новый BordRow, сохранить его в базе данных и вернуть весь объект Bord? Параметр content имеет вид: {title: "Test Row", bord_id: 1}

Исключение:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: Bord.rows, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.write(AbstractPersistentCollection.java:409) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
    at org.hibernate.collection.internal.PersistentBag.add(PersistentBag.java:383) ~[hibernate-core-5.4.6.Final.jar:5.4.6.Final]
    at WebSocketController.create(WebSocketController.java:47) ~[main/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_221]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_221]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_221]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_221]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) ~[spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) ~[spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:565) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:511) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:94) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:520) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:454) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:144) [spring-messaging-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_221]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_221]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]

Класс Bord:

@Table(name = "bords")
@Entity
public class Bord
{
    @Id
    @GeneratedValue
    private int id;

    @NotNull
    private String name;

    @Column
    private String icon;

    @Column
    private String background;

    @OneToMany(mappedBy = "bord", fetch = FetchType.LAZY)
    @JsonIgnore
    private List<BordRow> rows;

    public Bord()
    {
        rows = new ArrayList<>();
    }

    public void addRow(BordRow row)
    {
        this.rows.add(row);
    }

    // Getters and setters
}

Класс BordRow:

@Entity
@Table(name = "bord_rows")
public class BordRow
{
    @Id
    @GeneratedValue
    private int id;

    @NotNull
    private String title;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "bord_id")
    @JsonIgnore
    private Bord bord;

    public BordRow(String title) {
        this.title = title;
    }

    // Getters and setters
}

Метод WebsocketController:

@MessageMapping("/bord_row/create")
@SendTo("/bord_row/created")
public Optional<Bord> create(String content) {
    JSONObject object = new JSONObject(content);
    Optional<Bord> bord = bordRepository.findById(object.getInt("bord_id"));

    if(bord.isPresent())
    {
        BordRow row = new BordRow(object.getString("title"));
        row.setBord(bord.get());
        List<BordRow> rows = bord.get().getRows();
        rows.add(row);
        bord.get().setRows(rows);
        bordRepository.save(bord.get());
    }

    return bord;
}

Метод WebsocketController другая попытка:

@MessageMapping("/bord_row/create")
@SendTo("/bord_row/created")
public Optional<Bord> create(String content) {
    JSONObject object = new JSONObject(content);
    Optional<Bord> bord = bordRepository.findById(object.getInt("bord_id"));

    if(bord.isPresent())
    {
        BordRow row = new BordRow(object.getString("title"));
        row.setBord(bord.get());
        bord.get().addRow(row);
        bordRepository.save(bord.get());
    }

    return bord;
}

1 Ответ

0 голосов
/ 10 ноября 2019

здесь вы загружаете объект из базы данных

Необязательно bord = bordRepository.findById (object.getInt ("bord_id"))

Список с BoardRows загружается лениво, что означает, что в ближайшее времяПосле завершения транзакции вы будете работать с прокси. Это ошибка, которую вы получили, потому что вы хотите добавить что-то на прокси.

Вы можете выполнить отложенную загрузку до активной загрузки, которая не требуется повторно из-за соображений производительности. Вы можете использовать EntityGraphs. Это позволяет вам загружать более глубокие объекты, даже если они загружены лениво.

Я надеюсь, что эта помощь

Matthias

...