我一直致力于解决各种问题,以使这个Spring-Hibernate应用程序正常运行。我可能犯了一个基本错误。
这似乎是一个反复出现的问题,许多答案都涵盖旧版本的Hibernate。我使用的是Spring 4.3.9和Hibernate 4.0.5
UT获取SessionFactory但getCurrentSession()返回null,在调试中我可以看到currentSessionContext为null。
的applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="data.xml"/>
</beans>
data.xml中
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
>
<!-- Enable autowiring -->
<tx:annotation-driven/>
<!-- context:annotation-config/-->
<bean id="myDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="packagesToScan" value="com.my"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.connection.pool-size">1</prop>
<prop key="hibernate.cache.provider_cache">org.hibernate.cache.NoCacheProvider</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>
</beans>
SpringConfig.java
package utils.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
@Configuration
@Import
(
{SpringRepositoryConfig.class
}
)
@ImportResource("classpath:configuration/applicationContext.xml")
public class SpringConfig
{
}
SpringRepositoryConfig.java
package utils.config;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import utils.persistence.ItemRepository;
import utils.persistence.HibernateItemRepositoryImpl;
import org.springframework.beans.factory.annotation.Autowired;
// Declare as a configuration class
@Configuration
public class SpringRepositoryConfig
{
@Autowired
SessionFactory sessionFactory;
// Define repository bean
@Bean
public ItemRepository itemRepository()
{
ItemRepository rep = new HibernateItemRepositoryImpl();
rep.setSessionFactory(sessionFactory);
return rep;
}
}
SpringServicesConfig.java
package utils.config;
import javax.inject.Inject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import bussysutils.persistence.ItemRepository;
import bussysutils.repository.DecoderLoadRepository;
import bussysutils.repository.DecoderLoadRepositoryImpl;
@Configuration
public class SpringServicesConfig
{
@Inject
ItemRepository repository;
@Bean
public DecoderLoadRepository decoderLoadRepository()
{
DecoderLoadRepositoryImpl decoderLoad = new DecoderLoadRepositoryImpl(repository);
return decoderLoad;
}
}
SessionConfig.java
package utils;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class SessionConfig
{
public static SessionFactory buildFactory(String url
,String user
,String password)
{
ServiceRegistry sr;
SessionFactory sfactory;
Configuration config = new Configuration();
config.setProperty("hibernate.connection.url", url);
config.setProperty("hibernate.connection.username", user);
config.setProperty("hibernate.connection.password", password);
StandardServiceRegistryBuilder ssrb
= new StandardServiceRegistryBuilder().applySettings(config.getProperties());
sr = ssrb.build();
try
{
sfactory = config.buildSessionFactory(sr);
}
catch (Throwable ex)
{
throw new ExceptionInInitializerError(ex);
}
return sfactory;
}
}
UT_DecoderLoad.java
import org.hibernate.SessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import utils.DecoderLoad;
import utils.SessionConfig;
import utils.config.SpringConfig;
import utils.persistence.HibernateItemRepositoryImpl;
import utils.persistence.ItemRepository;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
@ContextConfiguration(classes = SpringConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class UT_DecoderLoad
{
@Autowired
SessionFactory sessionFactory;
@Test
public void decoderLoadTest()
{
try
{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
sessionFactory = SessionConfig.buildFactory("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=my-host-name.my.com)(PORT=1521))(CONNECT_DATA=(SERVER=dedicated)(SERVICE_NAME=dev)))"
,"myuser"
,"mypassword");
}
catch (SQLException e)
{
System.err.println("uploadServlet ERROR - " + e.getMessage());
System.out.print("uploadServlet logon ERROR - SQLException: " + e.getMessage());
e.printStackTrace();
}
Session s = sessionFactory.getCurrentSession(); /// <<<<<<<<
s.beginTransaction();
DecoderLoad decoderLd = new DecoderLoad();
decoderLd.setSiteRefNo("123456");
System.out.println(decoderLd.getSiteRefNo());
// update the database
ItemRepository itemRepo = new HibernateItemRepositoryImpl();
// itemRepo.create(decoderLd);
s.save(decoderLd);
s.getTransaction().commit();
}
}
答案 0 :(得分:0)
您正在为自己制作非常复杂的东西,首先您要混合基于XML和Java的配置,并且您有一个单个bean的配置类。要么使用Java或XML,要么不要混用它们,特别是如果你不确定那些事情是做什么的。
您的LocationRequest.setPriority(PRIORITY_HIGH_ACCURACY)
设置也存在缺陷,因为它是部分设置DataSource
。
接下来,由于使用DataSource
(基本上使您的Spring配置无效),SessionFactory
配置基本无用。你不应该使用SessionConfig
,所以放弃它。 XML中的SessionConfig
配置也存在缺陷,SessionFactory
属性不会执行任何操作,因为注入hibernate.connection
并且您不应该使用DataSource
除非您使用JTA。 Spring会为你管理它。
您的单元测试也存在缺陷,您应该注入存储库而不是自己创建新实例。
如果说并将所有内容移动到xml,hibernate.current_session_context
应该看起来像这样。
data.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context">
<tx:annotation-driven/>
<context:property-placeholder location="jdbc.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.my"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.cache.provider_cache">org.hibernate.cache.NoCacheProvider</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernatTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="itemRepository" class="utils.config.HibernateItemRepositoryImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="decoderLoadRepository" class="utils.config.DecoderLoadRepositoryImpl">
<constructor-arg ref="itemRepository" />
</bean>
</beans>
将包含以下内容
jdbc.properties
现在,您可以删除jdbc.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=my-host-name.my.com)(PORT=1521))(CONNECT_DATA=(SERVER=dedicated)(SERVICE_NAME=dev)))
jdbc.username=myuser
jdbc.password=mypassword
,SessionConfig
和SpringServicesConfig
类,因为在配置类过时的情况下,您不应该首先将类添加到xml文件。
现在你的测试也有缺陷,因为它应该是SpringRepositoryConfig
并且应该加载XML文件而不是java配置。
@Transactional
虽然不确定你在这里测试什么,但你应该测试@ContextConfiguration("classpath:configuration/applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public class UT_DecoderLoad {
@Autowired
SessionFactory sessionFactory;
@Test
public void decoderLoadTest() {
Session s = sessionFactory.getCurrentSession(); /// <<<<<<<<
DecoderLoad decoderLd = new DecoderLoad();
decoderLd.setSiteRefNo("123456");
System.out.println(decoderLd.getSiteRefNo());
s.save(decoderLd);
s.flush(); // "simulate a commit"
}
}
。
HibernateItemRepositoryImpl
答案 1 :(得分:0)
这是我当前的版本,它运行但不更新数据库表。
data.xml中
const express = require('express');
const router = express.Router();
const request = require('request');
// Config for health check endpoint
const healthCheckURL = 'https://SOME_ENDPOINT/health';
const zone = 'DEV';
// Initialize Prometheus
const Prometheus = require('prom-client');
const collectDefaultMetrics = Prometheus.collectDefaultMetrics;
collectDefaultMetrics({
timeout: 5000
});
router.get('/', (req, res) => {
res.end(Prometheus.register.metrics());
});
const serviceHealthGauge = new Prometheus.Gauge({
name: 'service_health',
help: 'Health of service component',
labelNames: ['zone']
});
setInterval(() => {
request({
url: healthCheckURL,
method: "GET",
},
function(error, response, body) {
if (!error && response.statusCode == 200) {
const JSONBody = JSON.parse(body);
// check service health
if (JSONBody.app && JSONBody.app.success) {
serviceHealthGauge.set({
zone: zone
}, 1);
} else {
serviceHealthGauge.set({
zone: zone
}, 0);
}
} else {
serviceHealthGauge.set({
zone: zone
}, 0);
}
}
);
}, 10000);
module.exports.metricNames = ['service_health'];
module.exports = router;
UT_DecoderLoad.java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
>
<!-- Enable autowiring -->
<tx:annotation-driven/>
<context:property-placeholder location="resources/jdbc.properties"/>
<bean id="DataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource"/>
<property name="packagesToScan" value="utils"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.cache.provider_cache">org.hibernate.cache.NoCacheProvider</prop>
<prop key="show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="itemRepository" class="utils.persistence.HibernateItemRepositoryImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="decoderLoadRepository" class="utils.repository.DecoderLoadRepositoryImpl">
<constructor-arg ref="itemRepository" />
</bean>
</beans>
我在db表中添加了一个主键列,以便我可以添加所需的@Id
DecoderLoad.java
import org.hibernate.SessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import utils.DecoderLoad;
import utils.persistence.ItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
@ContextConfiguration("classpath:configuration/applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public class UT_DecoderLoad
{
@Autowired
SessionFactory sessionFactory;
@Autowired
ItemRepository itemRepo;
@Test
public void decoderLoadTest()
{
DecoderLoad decoderLd = new DecoderLoad();
decoderLd.setSiteRefNo("123456");
decoderLd.setDecoderNo("999");
System.out.println(decoderLd.getSiteRefNo());
itemRepo.create(decoderLd);
sessionFactory.getCurrentSession().flush();
}
}
我还将javassist添加到pom。
Maven编译抱怨:
package utils;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
@Table(name = "Decoder_Load")
public class DecoderLoad
{
public DecoderLoad()
{
}
// pojo with annotations
@Id
@Column(name = "decoder_no")
private String decoderNo;
...
这个简单的测试运行但没有插入记录而不强制它并导致其他问题。
编辑:刚刚了解到测试会进行回滚,因此不会提交。