没有xml文件的Hibernate4配置 - sessionFactory为null

时间:2014-05-27 09:19:59

标签: java hibernate

我有一个使用Spring3和Hibernate4的Web项目,现在我想在不使用xml文件的情况下测试DAO。为此,我创建了一个类,该类创建了一个LocalSessionFactoryBean,其中包含应用程序的xml文件中包含的数据和一个简单的测试类。

但是, localSessionFactoryBean.getObject()返回的 sessionFactory 为null。我一直在研究像this这样的例子,当我修改它们以便在没有Spring的情况下运行时它们会遇到同样的问题。你有什么想法吗?

这是准备sessionFactory的代码:

@Configuration
@Transactional
@EnableTransactionManagement
@ComponentScan({ "com.company" })
public class HibernateInitializator {

    public SessionFactory getSessionFactory() {

        Properties hibernateProperties = getHibernateProperties();
        DataSource dataSource = getDatasourceConfiguration();
        LocalSessionFactoryBean localSessionFactoryBean = generateSessionFactoryBean(new String[] { "com.company" },
            dataSource, hibernateProperties);
        SessionFactory sessionFactory = localSessionFactoryBean.getObject();

        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(sessionFactory);

        return sessionFactory;
    }

    private DataSource getDatasourceConfiguration() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/dbName");
        dataSource.setUsername("username");
        dataSource.setPassword("password");

        return dataSource;
    }

    private static LocalSessionFactoryBean generateSessionFactoryBean(String[] basePackage, DataSource dataSource,
        Properties hibernateProperties) {

        LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
        localSessionFactoryBean.setDataSource(dataSource);
        localSessionFactoryBean.setPackagesToScan(basePackage);
        localSessionFactoryBean.setHibernateProperties(hibernateProperties);

        return localSessionFactoryBean;
    }

    private static Properties getHibernateProperties() {

        Properties hibernateProperties = new Properties();
        hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
        hibernateProperties.put("hibernate.show_sql", false);
        hibernateProperties.put("hibernate.generate_statistics", false);
        hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
        hibernateProperties.put("hibernate.use_sql_comments", false);

        return hibernateProperties;
    }
}

这是一个使用它的简单测试类:

public class GenericDAOHibernateTest {

    private GenericDAOHibernate dao;

    @BeforeTest
    private void testInitialization() {

        dao = new GenericDAO();
        HibernateInitializator initializator = new HibernateInitializator();
        SessionFactory sessionFactory = initializator.getSessionFactory();
        dao.setSessionFactory(sessionFactory);
    }

    @Test(description = "Checks that returns the user list ")
    public void shouldReturnsUserList() throws SQLException, Exception {

        List<Object[]> openResultSetList = dao.doSomeOperation();
        ...
    }
}

3 个答案:

答案 0 :(得分:12)

尝试添加此行

localSessionFactoryBean.afterPropertiesSet();
设置LocalSessionFactoryInstance属性后的方法中的

。你的方法将是

private static LocalSessionFactoryBean generateSessionFactoryBean(String[] basePackage, DataSource dataSource,
        Properties hibernateProperties) {
        LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
        localSessionFactoryBean.setDataSource(dataSource);
        localSessionFactoryBean.setPackagesToScan(basePackage);
        localSessionFactoryBean.setHibernateProperties(hibernateProperties);
        // Added the below line
        localSessionFactoryBean.afterPropertiesSet();
        return localSessionFactoryBean;
    }

link可能会为问题增加更多洞察力。

根据文档,

public void afterPropertiesSet()抛出IOException

  

在BeanFactory设置了所有提供的bean属性(并且满足BeanFactoryAware和ApplicationContextAware)之后,由BeanFactory调用。   此方法允许bean实例仅在设置了所有bean属性时执行初始化,并在配置错误时抛出异常。

在您的情况下,我认为您需要手动在代码中调用它。

答案 1 :(得分:3)

我问过如何在没有xml文件的情况下执行此操作,@ Octopus提出的解决方案解决了我遇到的问题。但是,在修复后出现其他错误的事务......所以我决定以不同的方式做这件事,不干扰应用程序。

为此,我在/ src / test / resources中创建了一个xml文件的简化版本,删除了许多配置,如c3p0的一个,并对这些值进行硬编码,以便在应用程序的属性文件发生更改时测试不会失败。

这是xml文件的内容:

<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" ...>

    <!-- Spring DataSource -->
    <bean id="testDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/testDatabase" />
        <property name="username" value="testUsername" />
        <property name="password" value="testPassword" />
    </bean>

    <!-- Hibernate 4 SessionFactory -->
    <bean id="testSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" p:dataSource-ref="testDataSource">
        <property name="packagesToScan" value="com.company" />
        <property name="hibernateProperties">
            <props>
                <!-- Hibernate basic configuration -->
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.generate_statistics">false</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.use_sql_comments">false</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="dataSource" ref="testDataSource" />
        <property name="sessionFactory" ref="testSessionFactory" />
    </bean>

    <context:annotation-config />
    <tx:annotation-driven />

    <!-- Initialization of DAOs -->
    <bean id="userDao" name="userDao" class="com.company.dao.UserDAOHibernate" autowire="byName"/>
    ... 
</beans>

在测试类中,我使用了JUnit,因为尽管我尝试扩展AbstractTestNGSpringContextTests,但还是没有设法使用TestNG。我建议使用JUnit 4.4版本而不是更新的版本,因为它有类似 AssumptionViolatedException 的类,由spring-test 2.5使用。

这是代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/test/resources/application-config-tests.xml" })
public class SimpleUserDAOTest {

    @Autowired
    private UserDAO dao;

    @Autowired
    private SessionFactory sessionFactory;

    @Before
    public void setUp() throws Exception {
        TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(sessionFactory.openSession()));
    }

    @After
    public void tearDown() throws Exception {
        SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
        SessionFactoryUtils.closeSession(sessionHolder.getSession());
    }

    @Test
    public void shouldReturnActiveUsers() {
        List<User> userList = dao.getActiveUsers();
        ...
    }
}

我希望这对您未来的发展有所帮助

答案 2 :(得分:0)

当您使用Spring 3+和Hibernate 4时,我建议您使用更好的方法,将所有内容定义为带注释的Spring配置,并且这项工作顺利进行。

下面是详细的代码,只需复制并粘贴到您的项目中,您可以在DAO层或任何弹簧组件的任何位置Autowire SessionFactory:)

@Configuration
@Import(HibernateConfig.class)
@EnableWebMvc
@ComponentScan(basePackages = "com.mypackages")
public class WebConfig extends WebMvcConfigurationSupport {

@Override
protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.parameterName("mediaType").ignoreAcceptHeader(true)defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", MediaType.APPLICATION_JSON);
}

@Bean(name = "validator")
public Validator validator() {
    return new LocalValidatorFactoryBean();
}
} 

然后定义HibernateConfig,如下所示:

@Configuration
@EnableTransactionManagement
@EnableAspectJAutoProxy
@PropertySource({"classpath:app.properties"})
@ComponentScan(basePackages = "com.mypackages")
public class HibernateConfig {

@Value(Constants.HIBERNATE_DIALECT)
private String hibernateDialect;

@Autowired
private DataSource dataSource;

@Bean(name = "appProperty")
public static PropertySourcesPlaceholderConfigurer appProperty() {
    return new PropertySourcesPlaceholderConfigurer();
}

@Bean(name = "sessionFactory")
public SessionFactory getSessionFactory() throws Exception {

    Properties properties = new Properties();
    properties.put(Constants.HIBERNATE_DIALECT_PROPERTY,
            hibernateDialect);
    properties.put(Constants.HIBERNATE_SHOW_SQL_PROPERTY,
            "false");
    properties
            .put(Constants.HIBERNATE_CURRENT_SESSION_CONTEXT_CLASS_PROPERTY,
                    "thread");
    properties
    .put("dynamic-update","true");
    LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
    factory.setPackagesToScan(new String[] { Constants.DOMAIN_MODEL_PACKAGE });
    factory.setDataSource(dataSource);
    factory.setHibernateProperties(properties);
    factory.afterPropertiesSet();
    return factory.getObject();
}

@Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager() throws Exception {
    return new HibernateTransactionManager(getSessionFactory());
}
}

然后定义JndiConfig,如下所示:

@Configuration
public class JndiConfig {

@Value(Constants.DRIVER_CLASS)
private String driverClassName;
@Value(Constants.DATABASE_URL)
private String databaseURL;
@Value(Constants.USER_NAME)
private String username;
@Value(Constants.PASSWORD)
private String password;
@Value(Constants.MAX_ACTIVE)
private int maxActive;
@Value(Constants.MAX_IDLE)
private int maxIdle;
@Value(Constants.MAX_WAIT)
private long maxWait;
@Value(Constants.MIN_IDLE)
private int minIdle;
@Value(Constants.INITIAL_SIZE)
private int initialSize;
@Value(Constants.TIME_BETWEEN_EVICTION)
private long timeBetweenEvictionRunsMillis;

@Bean(name = "dataSource")
public DataSource dataSource() throws Exception {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName(driverClassName);
    dataSource.setUrl(databaseURL);
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    dataSource.setTestOnBorrow(true);
    dataSource.setTestWhileIdle(true);
    dataSource.setValidationQuery("SELECT 1");
    dataSource.setMaxActive(maxActive);
    dataSource.setMaxIdle(maxIdle);
    dataSource.setMaxWait(maxWait);
    dataSource.setMinIdle(minIdle);
    dataSource
            .setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

    return dataSource;
}
}