spring-data-jpa Hibernate 混淆 - 我 应该 在 Spring 启动 时 使用 存储 库 还是 会话

mzillmmw  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(133)

Definitely confused here, I use spring boot to create 2 simple classes where the child class has a one-to-many with parent class
I save records using the repository pattern, but when I look up the parent record, I get a lazyinitializationexception for the child records.
Am I supposed to use hibernate session instead of repository?

@Autowired  CustomerRepository customerRepository;
@Autowired  ProductRepository productRepository;

Customer bob = new Customer("Bob");
customerRepository.save(bob);
productRepository.save(new Product("p1", 1, bob));
productRepository.save(new Product("p2", 1, bob));

Customer mycustomer = session.findCustomerByName("Bob");

System.out.printf(mycustomer.getProducts().toString());   // generates exception

Standard repository interfaces

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
    Customer findCustomerByName(String name);
}

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}

Simple entity classes

@Entity
@Table(name = "customer")
@Getter @Setter
@NoArgsConstructor
public class Customer {
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue
    private Long id;

    @Column(name = "name")
    private String name;

    public Customer(String name) {
        this.name = name;
    }

    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Product> products = new ArrayList<>();

And

@Entity
@Table(name = "product")
@Data
@NoArgsConstructor
public class Product {
    @Id
    @GeneratedValue
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "qty")
    private Integer qty;
    @ManyToOne
    @JoinColumn(name = "customer_id")
    private Customer customer;

    public Product(String name, Integer qty, Customer customer) {
        this.name = name;
        this.qty = qty;
        this.customer = customer;
    }
}

Not sure if I need to be getting a hibernate session if I use the methods from repository.
What am I missing?

dtcbnfnu

dtcbnfnu1#

OneToMany is default LAZY and you are accessing collection outside of hibernate session(running transaction). Even the list is empty a select is needed to initialize lazy collection. Persistence cannot know if there are items in collection, unless it checks in DB.
options:

  • FetchType.EAGER
  • join fetch rels r in your JPQL
  • initialize collection inside transaction/session

Another option to avoid Lazy initiliazation exception is using a stream to count objects in order to execute the query to bring the childs.

相关问题