【问题标题】:javax.persistence.TransactionRequiredException Error: jpa 2 + hibernate - Native Queryjavax.persistence.TransactionRequiredException 错误:jpa 2 + hibernate - 本机查询
【发布时间】:2014-06-19 11:48:37
【问题描述】:

我在尝试更新 sphinx 实时索引时遇到上述错误。由于 sphinx 使用非常接近 mysql 的数据库,我正在尝试使用实体管理器来更新索引。但是 sphinxql 不是一个完整的 mysql 数据库,所以如果我使用 entitymanager.merge 方法,sphinxql 无法理解生成的 sql。因此,我决定使用 createNativeQuery 从实时索引中插入新索引或删除索引。但是,当我调用 createNativeQuery 的 .executeUpdate 方法时,标题中出现异常。

这是我的道:

public interface RTIndexGeoDao {

    public boolean deleteIndex(long id);

    public boolean insertIndex(long id, long agentActivityId, long agentId, double latitude, double longitude);
}

这是我的 Dao 实现:

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

@Repository(value = "rtIndexGeoDao")
public class JPARTIndexDao implements RTIndexGeoDao {

    private EntityManager em;

    @PersistenceContext(unitName = "rtIndexPU")
    public void setRtIndexEntityManager(EntityManager em)
    {
        this.em = em;
    }

    public boolean deleteIndex(long id) {
        //This is to update our geodistance index
        try
        {
            this.em.createNativeQuery("delete from rt_geo where agent_agent_id = ?1").setParameter(1, id).executeUpdate();


            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public boolean insertIndex(long id, long agentActivityId, long agentId,
            double latitude, double longitude) {
        try
        {
            this.em.createNativeQuery("insert into rt_geo(id, agent_activity_id, agent_agent_id, latitude, longitude) values(?1, ?2, ?3, ?4, ?5)")
            .setParameter(1, id)
            .setParameter(2, agentActivityId)
            .setParameter(3, agentId)
            .setParameter(4, latitude)
            .setParameter(5, longitude).executeUpdate();

            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }

}

这是我的 RTIndexManager:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springtest.mavenspringapp.repository.RTIndexGeoDao;

@Component
@Transactional
public class SphinxRTIndexManagerImpl implements SphinxRTIndexManager {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Autowired
    private RTIndexGeoDao rtIndexGeoDao;

    public boolean deleteIndex(long id) {
        return rtIndexGeoDao.deleteIndex(id);
    }

    public boolean insertIndex(long id, long agentActivityId, long agentId,
            double latitude, double longitude) {
        return rtIndexGeoDao.insertIndex(id, agentActivityId, agentId, latitude, longitude);
    }

}

这是我的 persistence.xml

<persistence-unit name="rtIndexPU" transaction-type="RESOURCE_LOCAL">
    </persistence-unit>

这是控制器:

@Autowired
    private SphinxRTIndexManager rtIndexManager;
private AgentActivity createActivity(Agent agent, double latitude, double longitude, String agentActivityDescription)
    {
//Steps to update indexes
        boolean deleteEntry = rtIndexManager.deleteIndex(agent.getAgentId());
        if (!deleteEntry) return null;

更新:我正在发布我的 applicationContext.xml

<!-- enabling annotation driven configuration /-->
    <context:annotation-config/>
<bean id="rtIndexEntityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:dataSource-ref="rtIndexDataSource"
        p:jpaVendorAdapter-ref="jpaAdapter">
        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>                             
        <property name="persistenceUnitName" value="rtIndexPU"></property>
    </bean>

<bean id="rtIndexTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
        p:entityManagerFactory-ref="rtIndexEntityManagerFactory"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    p:entityManagerFactory-ref="entityManagerFactory"/>

我有另一个持久性单元,每个经理、dao 等都可以工作。但是当我在persistenceContext为rtIndexPU的实体管理器上使用createNativeQuery.executeUpdate时,就会出现这个异常:

javax.persistence.TransactionRequiredException:执行更新/删除查询

我搜索了互联网上所有可用的问题,但无法解决这个问题。提前致谢。

【问题讨论】:

  • 请同时发布您的 Spring 配置
  • 我编辑了我的问题。
  • 你的配置中有 吗?
  • 是的,但我忘了在这里发布。

标签: java mysql spring hibernate


【解决方案1】:

由于您的代码中有两个事务管理器,问题很可能是您的SphinxRTIndexManagerImpl 没有使用正确的一个(或任何一个)。

您应该将代码更改为:

@Component
@Transactional("rtIndexTransactionManager")
public class SphinxRTIndexManagerImpl implements SphinxRTIndexManager {

}

您还必须配置第二个事务管理器 (rtIndexTransactionManager) 以使用注释,方法是:

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

【讨论】:

  • 其实就是这样!感谢您的帮助。我希望这可以帮助其他有同样问题的人。我发现的大多数答案都表明在事务之前使用 beginTransaction 。也就是说,建议手动处理事务
  • @JorgeCespedes 很高兴帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 2017-12-16
  • 2019-10-27
  • 1970-01-01
  • 2011-03-09
  • 2017-06-04
相关资源
最近更新 更多