java - 无法在 hibernate 中使用延迟加载来获取数据

标签 java hibernate

嗨,我正在尝试在 hibernate 中编写一段代码来延迟加载具有以下架构的表员工的数据。但出现异常,提示 session 不可用。谁可以帮我这个事。提前致谢。

  CREATE TABLE employees
  (
    employee_id NUMBER 
                GENERATED BY DEFAULT AS IDENTITY START WITH 108 
                PRIMARY KEY,
    first_name VARCHAR( 255 ) NOT NULL,
    last_name  VARCHAR( 255 ) NOT NULL,
    email      VARCHAR( 255 ) NOT NULL,
    phone      VARCHAR( 50 ) NOT NULL ,
    hire_date  DATE NOT NULL          ,
    manager_id NUMBER( 12, 0 )        , -- fk
    job_title  VARCHAR( 255 ) NOT NULL,
    CONSTRAINT fk_employees_manager 
        FOREIGN KEY( manager_id )
        REFERENCES employees( employee_id )
        ON DELETE CASCADE
  );

第1步:我的 hibernate 配置如下

public class Config {
    private static final SessionFactory sessionFactory;
    static {
        try {
            Properties properties = new Properties();
            properties.setProperty("hibernate.connection.url", "jdbc:oracle:thin:@localhost:1521:orcl");
            properties.setProperty("hibernate.connection.username", "ot");
            properties.setProperty("hibernate.connection.password", "yourpassword");
            properties.setProperty("dialect", "org.hibernate.dialect.OracleDialect");
            properties.setProperty("hibernate.hbm2ddl.auto", "validate");
            properties.setProperty("hibernate.connection.driver_class", "oracle.jdbc.driver.OracleDriver");
            sessionFactory = new Configuration()
                    .addProperties(properties)
                    .addAnnotatedClass(Employee.class)
                    .buildSessionFactory();
        }catch(Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static Session getSession() throws Exception{
        return sessionFactory.openSession();
    }
}

第2步:Hibernate映射如下完成

@Entity
@Table(name="Employees")
public class Employee {

    @Id
    @Column(name="employee_id")
    private int employeeId;

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

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

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

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

    @Column(name="hire_date")
    @Temporal(TemporalType.DATE)
    private Date hireDate;

    @ManyToOne(cascade= {CascadeType.ALL})
    @JoinColumn(name="manager_id")
    private Employee manager;

    @OneToMany(mappedBy="manager", fetch=FetchType.LAZY)
    private Set<Employee> subOrdinates = new HashSet<Employee>();

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

    //getters and setters
}

第3步:我正在尝试获取一名员工的下属。就像如果员工e1的经理id为1,那么emp e1是employee_id为1的员工m1的下属。我在dao类中编写了以下代码。

public Set<Employee> getSubOrdinates(int id) {
    Set<Employee> subOrdinates = null;
    try {
        Session session = Config.getSession();
        Transaction transaction = session.beginTransaction();
        Employee emp = session.get(Employee.class, id);
        subOrdinates = emp.getSubOrdinates();
        transaction.commit();
        session.close();
    }catch(Exception e) {
        e.printStackTrace();
    }
    return subOrdinates;
}

运行 DAO 类的 getSubOrdinates() 方法后,出现错误,提示 session 不可用。

INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.buynow.entity.Employee.subOrdinates, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
    at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:188)
    at com.buynow.driver.EmployeeDriver.main(EmployeeDriver.java:12)

最佳答案

Hibernate 返回延迟加载集合的代理对象。在您的情况下 subOrdinates = emp.getSubOrdinates(); 将返回一个代理。并且在您迭代数据之前它不会加载数据。您可能会在此方法之外使用此 Set,并且由于 Session 已在此方法中关闭,因此它将抛出异常。一种方法是将 Service 方法包装在事务中,另一种方法是仅迭代 getSubOridinate 方法中的 Set,或者您可以使用 HQL 覆盖查询中的延迟加载。

关于java - 无法在 hibernate 中使用延迟加载来获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57942779/

相关文章:

java - 使用 hibernate 和 gilead for gwt 添加到实体类中保存的列表时出现 LazyInitializationException

java - 在我的 xhtml 中使用模板 (jsf) 后,commandLink 和 CommandButton 标记不会调用任何操作

java - 使用 Java/Hibernate 归档

hibernate - Spring Data 悲观锁超时与 Postgres

Java Hibernate @OneToMany 标准投影返回 NULL

java - 我的 Jframe 在执行 java 程序期间不可见。在我调整框架大小后,所有字段都可见

java - 当我运行程序时循环重复两次

java - 使用 Java 为迷宫创建 GUI

java - Hibernate DAO 将对象值设置为对象

java - 在 Spring 应用程序中配置 Hibernate