@OneToMany @JoinTable failed to lazily initialize a collection Fehler

Schuriko

Bekanntes Mitglied
Ich erstelle mir gerad ein Projekt. Folgend ein Auszug daraus. Ich habe eine Entity "Project" und "File". Ein Project kann beliebig viele Files haben. Also eine OneToMany. Da ich File noch an anderer Stelle verwende verbinde ich die beiden über eine Join-Table.

Java:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

@Entity
@Table(name="projects")
public class Project {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
   
    @CreationTimestamp
    private Date    created_at;
   
    @OneToOne(cascade = CascadeType.REMOVE, fetch=FetchType.EAGER)
    @JoinColumn(name="created_by")       
    private User    created_by;
   
    @UpdateTimestamp
    private Date    updated_at;
   
    @OneToOne(cascade = CascadeType.REMOVE, fetch=FetchType.EAGER)   
    @JoinColumn(name="updated_by")       
    private User    updated_by;   
   
    @NotNull
    private Boolean    published = false;
   
    @Size(min=3, max=255)
    @NotBlank       
    private String    name;

    @Size(min=3, max=10)
    private String    key;
   
    @Max(255)
    private String    symbol;
   
    private Integer    color = 0;
   
    @Lob
    private String    description;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "project_files")   
    private List<File> files = new ArrayList<>();
   
    public Project() {
        super();
    }
   
    public Project(@Size(min = 3, max = 255) @NotBlank String name) {
        super();
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getCreatedAt() {
        return created_at;
    }

    public void setCreatedAt(Date created_at) {
        this.created_at = created_at;
    }

    public User getCreatedBy() {
        return created_by;
    }

    public void setCreatedBy(User created_by) {
        this.created_by = created_by;
    }

    public Date getUpdatedAt() {
        return updated_at;
    }

    public void setUpdatedAt(Date updated_at) {
        this.updated_at = updated_at;
    }

    public User getUpdatedBy() {
        return updated_by;
    }

    public void setUpdatedBy(User updated_by) {
        this.updated_by = updated_by;
    }

    public Boolean getPublished() {
        return published;
    }

    public void setPublished(Boolean published) {
        this.published = published;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getSymbol() {
        return symbol;
    }

    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }

    public Integer getColor() {
        return color;
    }

    public void setColor(Integer color) {
        this.color = color;
    }

    public String getDescription() {
        return description;
    }

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

    public List<File> getFiles() {
        return files;
    }

    public void setFiles(List<File> files) {
        this.files = files;
    }

    @Override
    public String toString() {
        return "Project [id=" + id + ", created_at=" + created_at + ", created_by=" + created_by + ", updated_at="
                + updated_at + ", updated_by=" + updated_by + ", published=" + published + ", name=" + name + ", key="
                + key + ", symbol=" + symbol + ", color=" + color + ", description=" + description + ", files=" + files
                + "]";
    }
       
}

Java:
import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

@Entity
@Table(name="files")
public class File {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
   
    @CreationTimestamp
    private Date    created_at;
   
    @OneToOne(cascade = CascadeType.REMOVE, fetch=FetchType.EAGER)
    @JoinColumn(name="created_by")       
    private User    created_by;
   
    @UpdateTimestamp
    private Date    updated_at;
   
    @OneToOne(cascade = CascadeType.REMOVE, fetch=FetchType.EAGER)   
    @JoinColumn(name="updated_by")       
    private User    updated_by;       
   
    @NotNull
    private Boolean    published = false;
   
    @Size(min=3, max=255)
    @NotBlank       
    private String    name;
   
    @Lob
    private String    description;
   
    @Size(min=3, max=255)
    @NotBlank       
    private String    filename;

    private String    type;
   
    public File() {
        super();
    }
   
    public File(@Size(min = 3, max = 255) @NotBlank String name, @Size(min = 3, max = 255) @NotBlank String filename) {
        super();
        this.name = name;
        this.filename = filename;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getCreatedAt() {
        return created_at;
    }

    public void setCreatedAt(Date created_at) {
        this.created_at = created_at;
    }

    public User getCreatedBy() {
        return created_by;
    }

    public void setCreatedBy(User created_by) {
        this.created_by = created_by;
    }

    public Date getUpdatedAt() {
        return updated_at;
    }

    public void setUpdatedAt(Date updated_at) {
        this.updated_at = updated_at;
    }

    public User getUpdatedBy() {
        return updated_by;
    }

    public void setUpdatedBy(User updated_by) {
        this.updated_by = updated_by;
    }

    public Boolean getPublished() {
        return published;
    }

    public void setPublished(Boolean published) {
        this.published = published;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

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

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "File [id=" + id + ", created_at=" + created_at + ", created_by=" + created_by + ", updated_at="
                + updated_at + ", updated_by=" + updated_by + ", published=" + published + ", name=" + name
                + ", description=" + description + ", filename=" + filename + ", type=" + type + "]";
    }   
   
   
}

Java:
import java.util.List;

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import com.abado.pts.entities.File;

public interface FileRepository extends CrudRepository<File, Long> {
    @Modifying
    @Query("delete from File f where f.id in ?1")
    void deleteWithIds(List<Long> ids);
   
    @Modifying
    @Query("update File set published = ?2 where id = ?1")
    void setPublished(Long id, Boolean publish);

    @Modifying
    @Query("update File set published = ?2 where id in ?1")
    void publishWidthIds(List<Long> ids, Boolean published);

}

Code:
import java.util.List;

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import com.abado.pts.entities.Project;

public interface ProjectRepository extends CrudRepository<Project, Long> {
   
    @Modifying
    @Query("delete from Project p where p.id in ?1")
    void deleteWithIds(List<Long> ids);
   
    @Modifying
    @Query("update Project set published = ?2 where id = ?1")
    void setPublished(Long id, Boolean publish);
   
    @Modifying
    @Query("update Project set published = ?2 where id in ?1")
    void publishWidthIds(List<Long> ids, Boolean published);
}

Java:
iimport java.util.Optional;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.abado.pts.entities.Language;
import com.abado.pts.entities.Project;
import com.abado.pts.repositories.LanguageRepository;
import com.abado.pts.repositories.ProjectRepository;

@Service
@Transactional
public class ProjectService {
   
    @Autowired
    ProjectRepository projectRepository;
   
    public Project save(Project project) {
        return projectRepository.save(project);
    }

    public Optional<Project> findById(Long id) {
        return projectRepository.findById(id);
    }
}

Java:
import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.abado.pts.entities.File;
import com.abado.pts.entities.Project;
import com.abado.pts.repositories.FileRepository;
import com.abado.pts.repositories.ProjectRepository;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProjectServiceTest {
   
    @Autowired
    ProjectService projectService;
   
    @Autowired
    ProjectRepository projectRepository;

    @Autowired
    FileRepository fileRepository;
   
    @Before
    public void setUp() throws Exception {
    }

    /**
     * test save without files
     */
    @Test
    public void testSaveWithoutFiles() {
        String  projectnameValue = "Project 1";
        Project project = new Project(projectnameValue);
       
        projectService.save(project);
       
        Optional<Project> foundProject = projectService.findById(project.getId());
       
        assertTrue(foundProject.isPresent());
        assertNotNull(foundProject.get().getCreatedAt());
        assertNotNull(foundProject.get().getUpdatedAt());
       
        // clear
        projectRepository.deleteAll();
        fileRepository.deleteAll();
    }
   
    /**
     * test save with files
     */
    @Test
    public void testSaveWithUnstoredFiles() {
        String  projectnameValue = "Project 1";
        List<File> files = new ArrayList<>();
        Project project = new Project(projectnameValue);
       
        files.add(new File("name1", "filename1"));
        files.add(new File("name2", "filename2"));
        files.add(new File("name3", "filename3"));

        assertEquals(3, files.size());
       
        project.setFiles(files);
        assertEquals(3, project.getFiles().size());
       
        assertNotNull(projectService.save(project));
       
        Optional<Project> foundProject = projectService.findById(project.getId());
       
        assertTrue(foundProject.isPresent());
        assertEquals("File Count: " + foundProject.get().getFiles().size(), 3, foundProject.get().getFiles().size());

        // clear
        projectRepository.deleteAll();
        fileRepository.deleteAll();
    }
   
}

Beim Test erhalte ich folgende Fehlermeldung
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: Project.files, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:597)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:216)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:160)
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:287)
at ProjectServiceTest.testSaveWithUnstoredFiles(ProjectServiceTest.java:96)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Ich verstehe nur nicht so ganz was ich falsch mache.
 

httpdigest

Top Contributor
Das Problem ist, dass du auf eine noch nicht initialisierte (weil lazy - @OneToMany werden per Default lazy nachgeladen) Collection Project.getFiles() außerhalb einer Transaktion innerhalb der Testmethode ProjectServiceTest.testSaveWithUnstoredFiles() zugreifst. Deine Transaktion erstreckt sich nur über den Service, aber eben nicht über deinen Unit-Test. Deshalb kann Hibernate die Datenbank nicht mehr fragen, um die Files eines Projektes nachzuladen.
Entweder, du lässt deine Transaktion über deinen Test erstrecken, oder du nutzt @OneToMany(fetch=EAGER).
 

Schuriko

Bekanntes Mitglied
Das Problem ist, dass du auf eine noch nicht initialisierte (weil lazy - @OneToMany werden per Default lazy nachgeladen) Collection Project.getFiles() außerhalb einer Transaktion innerhalb der Testmethode ProjectServiceTest.testSaveWithUnstoredFiles() zugreifst. Deine Transaktion erstreckt sich nur über den Service, aber eben nicht über deinen Unit-Test. Deshalb kann Hibernate die Datenbank nicht mehr fragen, um die Files eines Projektes nachzuladen.
Entweder, du lässt deine Transaktion über deinen Test erstrecken, oder du nutzt @OneToMany(fetch=EAGER).
Danke es funktioniert. Ich habe die @OneToMany jetzt wie folgt
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Hibernate oneToMany Syntaxfehler Datenbankprogrammierung 3
OnDemand Hibernate OneToMany ManyToOne Datenbankprogrammierung 61
K bidirektionale OneToMany Endlosschleife Datenbankprogrammierung 6
M Problem mit JPA - OneToMany-Relation Datenbankprogrammierung 3
S Derby/JavaDB OpenJPA, @oneToMany und Probleme Datenbankprogrammierung 2
turmaline [Hibernate] @OneToMany - Eine referenzierte Tabelle abfragen Datenbankprogrammierung 11
J MySQL Hibernate: Probleme beim Speichern von OneToMany - Datensätzen Datenbankprogrammierung 2
I JAVADB (Derby) OneToMany Datenbankprogrammierung 2
A JPA + @OneToMany + String ArrayList Datenbankprogrammierung 4
GilbertGrape hibernate: Problem mit OneToMany Datenbankprogrammierung 4
G Hibernate oneToMany Not null Datenbankprogrammierung 4
S Reverse @OnToMany @JoinTable Datenbankprogrammierung 8
P Many to Many mit JoinTable Datenbankprogrammierung 2
M JPA Annotations @JoinTable oder eigenes Mapping Datenbankprogrammierung 13
R Mongodb Authentication failed Datenbankprogrammierung 6
T org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ..., could not initialize proxy - no Session Datenbankprogrammierung 5
Kirby.exe Authentification Failed Datenbankprogrammierung 3
E Conversion failed when converting date and/or time from character string. Datenbankprogrammierung 3
C jpa, exception Predeployment of PersistenceUnit failed Datenbankprogrammierung 1
G SQLLite error code 0x13: constraint failed Datenbankprogrammierung 7

Ähnliche Java Themen

Neue Themen


Oben