Java 没有xml文件的Hibernate4配置-sessionFactory为空
我有一个使用Spring3和Hibernate4的web项目,现在我想在不使用xml文件的情况下测试DAO。为此,我创建了一个类,该类使用应用程序xml文件中包含的数据和一个简单的测试类创建一个LocalSessionFactoryBean 但是,localSessionFactoryBean.getObject()返回的sessionFactory为null。我一直在看一些例子,比如,当我修改它们以在没有Spring的情况下运行时,它们也有同样的问题。你知道吗 这是准备sessionFactory的代码:Java 没有xml文件的Hibernate4配置-sessionFactory为空,java,hibernate,Java,Hibernate,我有一个使用Spring3和Hibernate4的web项目,现在我想在不使用xml文件的情况下测试DAO。为此,我创建了一个类,该类使用应用程序xml文件中包含的数据和一个简单的测试类创建一个LocalSessionFactoryBean 但是,localSessionFactoryBean.getObject()返回的sessionFactory为null。我一直在看一些例子,比如,当我修改它们以在没有Spring的情况下运行时,它们也有同样的问题。你知道吗 这是准备sessionFacto
@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();
...
}
}
公共类GenericDAOHibernateTest{
私有的genericdao和hibernate-dao;
@试验前
私有无效证明初始化(){
dao=新的GenericDAO();
HibernateInitializator初始化器=新的HibernateInitializator();
SessionFactory SessionFactory=initializator.getSessionFactory();
dao.setSessionFactory(sessionFactory);
}
@测试(description=“返回用户列表的检查”)
public void shouldReturnsUserList()抛出SQLException,Exception{
List openResultSetList=dao.doSomeOperation();
...
}
}
尝试添加此行
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;
}
这可能会为问题增加更多的洞察力
根据文件
public void afterPropertieSet()引发IOException
由BeanFactory在设置所有提供的bean属性(并满足BeanFactoryAware和ApplicationContextAware)后调用。
此方法允许bean实例仅在设置了所有bean属性时执行初始化,并在配置错误时抛出异常
在您的情况下,我认为您需要在代码中手动调用它。当您使用Spring 3+和Hibernate 4时,我建议您使用一种更好的方法,将所有内容定义为带注释的Spring配置,这样可以顺利地工作 下面是详细的代码,只需复制并粘贴到您的项目中,您就可以
Autowire
SessionFactory在DAO层或任何spring组件中的任何位置:)
然后定义一个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());
}
}
@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;
}
}
然后定义一个JndiConfig
,如下所示:
@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());
}
}
@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;
}
}
我问过如何在没有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>
org.hibernate.dialogue.mysql5innodbdialogue
假的
假的
更新
假的
...
在测试类中,我使用了JUnit,因为尽管我尝试扩展AbstractTestNGSpringContextTests,但我还没有成功地使用TestNG。我建议使用JUnit 4.4版本而不是更新的版本,因为它有类似AssumptionViolatedException的类,这些类由SpringTest2.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();
...
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(位置={“文件:src/test/resources/application-config-tests.xml”})
公共类SimpleUserDAOTest{
@自动连线
私用刀刀;
@自动连线
私人会话工厂会话工厂;
@以前
public void setUp()引发异常{
TransactionSynchronizationManager.bindResource(sessionFactory,新会话持有者(sessionFactory.openSession());
}
@之后
public void tearDown()引发异常{
SessionHolder SessionHolder=(SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
@试验
public void shouldReturnActiveUsers(){
List userList=dao.getActiveUsers();
...
}
}
我希望这对您将来的开发有所帮助谢谢,通过这一行,sessionFactory已正确初始化。现在我在使用DAO时遇到了问题,因为它启动了HibernateException(“当前线程找不到会话”),尽管我添加了@Transactional之类的注释。我已经找了一段时间了,但还没有找到解决方法。我会在这里评论它,只要我觉得它很高兴,它有帮助。您可以在此处创建新问题并寻求帮助。如果你自己找到了答案,那么就把它贴出来并接受它。在尝试了一段时间后,我决定不这样做。我把它贴在这里作为一个不同的答案,以便其他人将来可以使用它。谢谢你的建议,我已经给了hibernate cfg配置位置。但是由于以下原因导致了以下错误:org.hibernate.service.UnknownUnwrapTypeException:无法在org.hibernate.engine.jdbc.connections.internal.driverManager连接ProviderImpl.unwrap(driverManager连接ProviderImpl.java:222)处展开为请求的类型[javax.sql.DataSource],谢谢。然而,我一直在尝试这段代码,但它对我不起作用,甚至没有启动Hibernate配置。可能我没有正确地注入依赖项,或者无法将其注入测试类。我还尝试过创建JndiConfig对象,并将数据源注入HibernateConfig对象,但没有成功。您是否将所有这些类都放在com.mypackages中了。如果是,请邮寄