首页 > 解决方案 > Hibernate5 忽略延迟加载

问题描述

我正在尝试使用hibernate5:

我的配置类:

@Configuration
@EnableTransactionManagement
public class HibernateConfiguration {

    @Value("${db.driver}")
    private String DB_DRIVER;

    @Value("${db.password}")
    private String DB_PASSWORD;

    @Value("${db.url}")
    private String DB_URL;

    @Value("${db.username}")
    private String DB_USERNAME;

    @Value("${hibernate.dialect}")
    private String HIBERNATE_DIALECT;

    @Value("${hibernate.show_sql}")
    private String HIBERNATE_SHOW_SQL;

    @Value("${entitymanager.packagesToScan}")
    private String ENTITYMANAGER_PACKAGES_TO_SCAN;

    @Value("${hibernate.enable_lazy_load_no_trans}")
    private String ENABLE_LAZY_LOAD;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }

    @Bean
    public PlatformTransactionManager hibernateTransactionManager() {
        HibernateTransactionManager transactionManager
                = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }


    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(DB_DRIVER);
        dataSource.setUrl(DB_URL);
        dataSource.setUsername(DB_USERNAME);
        dataSource.setPassword(DB_PASSWORD);
        return dataSource;
    }

    private final Properties hibernateProperties() {
        Properties hibernateProperties = new Properties();
        hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
        hibernateProperties.put("hibernate.show_sql", HIBERNATE_SHOW_SQL);
        hibernateProperties.put("hibernate.enable_lazy_load_no_trans", ENABLE_LAZY_LOAD);

        return hibernateProperties;
    }

}

和我的 DAO:

@Service("userDAO_mysql")
@Transactional
public class UserDAOImpl implements UserDAO {
    @Override
    public User getAllUsers(){
        Session session = sessionFactory.getCurrentSession();
        return session.getSession().get(User.class,0);
    }
}

我的用户将 FetchType 设置为 LazyLoad 到任何@OneToMany关系。但是,所有关系都是通过使用加载的:

User u = userDAO.getAllUsers();

否则我没能做到。有什么技巧可以让它正常工作吗?或者我错过了什么?

感谢帮助!

// 编辑,只是为了澄清,到目前为止我一直在使用它,并决定使用更相关的方式:

public class HibernateUtil {
    private static StandardServiceRegistry registry;
    private static SessionFactory sessionFactory;

    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                // Create registry
                registry = new StandardServiceRegistryBuilder()
                        .configure()
                        .build();

                // Create MetadataSources
                MetadataSources sources = new MetadataSources(registry);

                // Create Metadata
                Metadata metadata = sources.getMetadataBuilder().build();

                // Create SessionFactory
                sessionFactory = metadata.getSessionFactoryBuilder().build();

            } catch (Exception e) {
                e.printStackTrace();
                if (registry != null) {
                    StandardServiceRegistryBuilder.destroy(registry);
                }
            }
        }
        return sessionFactory;
    }

    public static void shutdown() {
        if (registry != null) {
            StandardServiceRegistryBuilder.destroy(registry);
        }
    }
}

public User getUserById(int id) {
    User u = null;
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = null;
    Integer employeeID = null;

    try {
        tx = session.beginTransaction();
        Criteria cr = session.createCriteria(User.class).add(Restrictions.eq("id",id));
        u = (User) cr.uniqueResult();
    } catch (HibernateException e) {
        if (tx!=null) tx.rollback();
        e.printStackTrace();
    } finally {
        session.close();
    }
    return u;
}

这种方式延迟加载没有被忽略,延迟加载:

    @OneToMany(mappedBy="user",cascade=CascadeType.ALL,fetch=FetchType.LAZY,
orphanRemoval=true)
    public Set<Topic> getTopics() {
        return topics;
    }

public void setTopics(Set<Topic> topics) {
    this.topics = topics;
}

标签: javaspringhibernatespring-boot

解决方案


让我们假设 parent 是第一个与 children 有 @onetomany 关系的实体,并且lazyload 在 @onetomany 上设置为 true

你仍然可以在服务类中调用 parent.getChildren() 方法,它会获取它们,但是如果你在你的控制器类中尝试这个,你会得到延迟加载异常。

当您只需要父对象时,此场景很有用,因此您只需检索父对象。如果您需要孩子,请调用您刚才提到的方法,它将为您检索该父母的所有孩子(在您的控制器类中)


推荐阅读