java - 为什么我无法检索刚刚保留的实体?

标签 java spring hibernate jax-ws hsqldb

我有这个 Web 服务,它基本上查询数据库并返回所有持久实体。出于测试目的,我创建了一个 TestDataManager,它在加载 Spring 上下文后保留 2 个示例实体(顺便说一句,我正在使用 JAX-WS、Spring、Hibernate 和 HSQLDB)。

我的 TestDataManager 看起来像这样:

@Component
public class TestDataManager {

@Resource
private SessionFactory sf;

@PostConstruct
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void insertTestData(){
    sf.openSession();
    sf.openSession().beginTransaction();
    sf.openSession().persist(new Site("site one"));
    sf.openSession().persist(new Site("site two"));
    sf.openSession().flush();
}
}

我的 JAX-WS 端点如下所示:

@WebService
public class SmartBrickEndpoint {

@Resource
private WebServiceContext context;

public Set<Site> getSitesForUser(String user){
    return getSiteService().findByUser(new User(user));
}

private ISiteService getSiteService(){
    ServletContext servletContext = (ServletContext) context.getMessageContext().get("javax.xml.ws.servlet.context");
    return (ISiteService) BeanRetriever.getBean(servletContext, ISiteService.class);
}
}

这是我的服务类:

@Component
@Transactional(readOnly = true)
public class SiteService implements ISiteService {

@Resource
private ISiteDao siteDao;

@Override
public Set<Site> findByUser(User user) {
    return siteDao.findByUser(user);
}
}

这是我的 DAO:

@Component
@Transactional(readOnly = true)
public class SiteDao implements ISiteDao {

@Resource
private SessionFactory sessionFactory;

@Override
public Set<Site> findByUser(User user) {
    Set<Site> sites = new LinkedHashSet<Site>(sessionFactory.getCurrentSession().createCriteria(Site.class).list());

    return sites;
}
}

这是我的 applicationContext.xml:

<context:annotation-config />
<context:component-scan base-package="br.unirio.wsimxp.dao"/>
<context:component-scan base-package="br.unirio.wsimxp.service"/>
<context:component-scan base-package="br.unirio.wsimxp.spring"/>

<bean id="applicationDS" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
    <property name="url" value="jdbc:hsqldb:file:sites"/>
</bean>

<bean id="sessionFactory"
      class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="applicationDS" />

    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.connection.release_mode">on_close</prop>
            <!--<prop key="hibernate.current_session_context_class">thread</prop>-->
            <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>
            <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
        </props>
    </property>
</bean>

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

<tx:annotation-driven transaction-manager="transactionManager" />

这就是现在发生的事情:

  1. 部署应用程序时,TestDataManager#insertTestData 启动(由于@PostConstruct)并且持久化不会引发任何异常。我现在数据库中应该有 2 个实体。
  2. 随后,我通过 SOAP 客户端调用端点,并且请求一直到达 DAO。 Hibernate 调用不会引发任何异常,但返回的列表为空。

奇怪的是,在 TestDataManager 中,如果我从 sf.openSession() 切换到 sf.getCurrentSession(),我会收到一条错误消息:“No Hibernate session 绑定(bind)到线程,并且配置不允许在此处创建非事务性 session 。

我在这里做错了什么?为什么查询“看不到”持久化实体?为什么我需要在 TestDataManager 上调用 sf.openSession(),尽管它是用 @Transactional 注释的?

我在 application.xml 中使用 hibernate.current_session_context_class=thread 进行了一些测试,但随后我只是在每个类中切换问题。我希望不需要手动调用 sf.openSession() 并将其留给 Hibernate 来处理。

非常感谢您的帮助!

最佳答案

我认为您需要在 insertTestData 上提交事务:

@PostConstruct
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void insertTestData(){
    Session session = sf.openSession();

    session.persist(new Site("site one"));
    session.persist(new Site("site two"));
    session.flush();
    session.close();
}

关于java - 为什么我无法检索刚刚保留的实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17371839/

相关文章:

java - Retrofit2 将正文作为 Json

java - Spring Stomp over Websocket : Message/Buffer/Cache/Stream limits

spring - findById() 给出未找到属性 ID

java - 在 Java Spring Maven Web 应用程序中调用 C/C++ 函数

java - 在哪里存储/访问 NetBeans 的 Java 可重用类

java - 即使应用程序被销毁也保持 'logged in'

java - 由于 hibernate 中的重复实体而引发异常

java - Spring Security 未应用于我的 URL

具有相同方法名称但不同限定符的 Spring bean 无法加载

hibernate - 在grails中直接通过ids建立关联