当前位置: 首页 > 知识库问答 >
问题:

SpringHibernate配置之谜

汪志业
2023-03-14

我现在正在研究Spring和冬眠,我遇到了一个我找不到答案的谜题。这是关于配置Hibernate以便与Spring一起使用。以下是Spring文档中的Spring beans xml配置示例:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
        </value>
    </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

您可以在这里看到,txManager bean的sessionFactory依赖项(我假设的sessionFactory类型)由sessionFactory bean覆盖,它实际上是LocalSessionFactoryBean类。但关键是LocalSessionFactoryBean没有实现SessionFactory,所以它不能用于注入依赖关系。您可以从LocalSessionFactoryBean接收SessionFactory,但为此您需要调用它的getObject方法,这里没有这样做。

这是我项目中的一个示例,但这次使用java配置:

package com.luv2code.springdemo.config;

import java.beans.PropertyVetoException;
import java.util.Properties;
import java.util.logging.Logger;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.luv2code.springdemo")
@PropertySource({ "classpath:persistence-mysql.properties" })
public class DemoAppConfig implements WebMvcConfigurer {

    @Autowired
    private Environment env;
    
    private Logger logger = Logger.getLogger(getClass().getName());
    
    // define a bean for ViewResolver

    @Bean
    public DataSource myDataSource() {
        
        // create connection pool
        ComboPooledDataSource myDataSource = new ComboPooledDataSource();

        // set the jdbc driver
        try {
            myDataSource.setDriverClass("com.mysql.jdbc.Driver");       
        }
        catch (PropertyVetoException exc) {
            throw new RuntimeException(exc);
        }
        
        // for sanity's sake, let's log url and user ... just to make sure we are reading the data
        logger.info("jdbc.url=" + env.getProperty("jdbc.url"));
        logger.info("jdbc.user=" + env.getProperty("jdbc.user"));
        
        // set database connection props
        myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
        myDataSource.setUser(env.getProperty("jdbc.user"));
        myDataSource.setPassword(env.getProperty("jdbc.password"));
        
        // set connection pool props
        myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
        myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
        myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));     
        myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));

        return myDataSource;
    }
    
    private Properties getHibernateProperties() {

        // set hibernate properties
        Properties props = new Properties();

        props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
        props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        
        return props;               
    }

    
    // need a helper method 
    // read environment property and convert to int
    
    private int getIntProperty(String propName) {
        
        String propVal = env.getProperty(propName);
        
        // now convert to int
        int intPropVal = Integer.parseInt(propVal);
        
        return intPropVal;
    }   
    
    @Bean
    public LocalSessionFactoryBean sessionFactory(){
        
        // create session factorys
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        
        // set the properties
        sessionFactory.setDataSource(myDataSource());
        sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
        sessionFactory.setHibernateProperties(getHibernateProperties());
        
        return sessionFactory;
    }
    
    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
        
        // setup transaction manager based on session factory
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(sessionFactory);

        return txManager;
    }   
    
}

如您所见,SessionFactory类型的transactionManager方法的参数是由SessionFactory bean自动连接的(这很奇怪,但现在不是重点),SessionFactory bean又是LocalSessionFactoryBean类,它没有实现SessionFactory接口,因此我们遇到了与xml配置相同的问题。

我在互联网上的好几个地方看到过这样的例子,所以我想知道它是如何工作的。

共有1个答案

谢洛城
2023-03-14

终于明白了。此处的文件说明:

Spring容器识别出LocalSessionFactoryBean实现了FactoryBean接口,因此特别对待这个bean:实例化了LocalSessionFactoryBean,但不是直接返回,而是调用getObject()方法。从这个调用getObject()返回的对象最终注册为sessionFactory bean。

 类似资料:
  • 在Spring Hibernate JTA项目中,我试图让异常处理工作。对于以下代码: 我试图捕捉底层hibernate/jdbc/db异常(例如,当依赖实体仍然存在时,删除将失败,并出现org . spring framework . ORM . hibernate 3 . hibernate JDBC exception)并执行一些操作。然而,catch代码永远不会到达。 但是如果我从我的方法

  • 我有一个应用程序,它使用spring 4 . 0 . 1 JPA hiba Nate 4 . 2 . 8(spring的JpaTransactionManager,localcontainereentitymanagerfactorybean,带有HibernateJpaDialect和apache的BasicDataSource作为数据源)进行数据库访问。在某个时刻,应用程序开始一个长时间运行的

  • 本文向大家介绍ASP.NET Core配置教程之读取配置信息,包括了ASP.NET Core配置教程之读取配置信息的使用技巧和注意事项,需要的朋友参考一下 提到“配置”二字,我想绝大部分.NET开发人员脑海中会立马浮现出两个特殊文件的身影,那就是我们再熟悉不过的app.config和web.config,多年以来我们已经习惯了将结构化的配置信息定义在这两个文件之中。到了.NET Core的时候,很

  • 本文向大家介绍跟我学Laravel之配置Laravel,包括了跟我学Laravel之配置Laravel的使用技巧和注意事项,需要的朋友参考一下 当你需要在运行时访问配置项时,可以使用Config类: 获取一个配置项的值** 如果配置项不存在,你还可以指定返回的默认值: 为配置项赋值 注意"点"式语法可以用来访问不同文件里的配置项的值。你还可以在运行时为配置项赋值。: 在程序运行时设置的配置值只在本

  • 本文向大家介绍SpringBoot之Java配置的实现,包括了SpringBoot之Java配置的实现的使用技巧和注意事项,需要的朋友参考一下 Java配置也是Spring4.0推荐的配置方式,完全可以取代XML的配置方式,也是SpringBoot推荐的方式。 Java配置是通过@Configuation和@Bean来实现的:   1、@Configuation注解,说明此类是配置类,相当于Spr

  • 本文向大家介绍Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析,包括了Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Thinkphp 框架配置操作之动态配置、扩展配置及批量配置。分享给大家供大家参考,具体如下: 动态配置 设置格式: 例如,我们需要动态改变数据缓存的有效期的话,可以使用 动态配置赋值仅