HibernateException:没有配置CurrentSessionContext(Hibernate4)

时间:2017-07-19 10:08:10

标签: spring hibernate annotations

我一直致力于解决各种问题,以使这个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();
  }
}

2 个答案:

答案 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 SessionConfigSpringServicesConfig类,因为在配置类过时的情况下,您不应该首先将类添加到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;
  ...

这个简单的测试运行但没有插入记录而不强制它并导致其他问题。

编辑:刚刚了解到测试会进行回滚,因此不会提交。