首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

使用JPA的EntityManager.persist()无法保存到数据库的有关问题

2012-10-29 
使用JPA的EntityManager.persist()无法保存到数据库的问题?我这两天刚开始使用JPA,遇到了一个问题,现象是

使用JPA的EntityManager.persist()无法保存到数据库的问题

?

我这两天刚开始使用JPA,遇到了一个问题,现象是这样的:使用EntityManager查询对象没有问题,但是持久化对象时,也就是使用entityMananger.persist()时,没有保存到数据库,此时程序没有也没有任何异常抛出。

?

忙了一天也没有搜索到解决方法,第二天和同事讨论,再次进行各种尝试,包括在persist前后加入transaction控制,如下:

?

entityManager.getTransaction().begin();entityManager.persist(it);entityManager.getTransaction().commit();

?

此时得到一个IllegalStateException:?“A JTA EntityManager cannot use getTransaction()”.

?

Google以上异常描述,得到以下Hibernate的源代码页面:

?

http://viewvc.jboss.org/cgi-bin/viewvc.cgi/hibernate/branches/Branch_3_2/HibernateExt/entitymanager/src/java/org/hibernate/ejb/AbstractEntityManagerImpl.java?view=markup&pathrev=11268

?

其中有一段代码是关于该异常的:

?

public EntityTransaction getTransaction() {if ( transactionType == PersistenceUnitTransactionType.JTA ) {throw new IllegalStateException( "A JTA EntityManager cannot use getTransaction()" );}return tx;}

?

看到“transactionType”字样,灵机一动,联想到在persistence.xml中有以下配置:

?

<persistence-unit name="IncidentTicketServicePU" transaction-type="JTA">

?

这时我想到这里的“transaction-type”可能需要设成其他值。搜索persistence.xml的schema定义“http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd”,在其中发现如下内容:

?

<xsd:simpleType name="persistence-unit-transaction-type">  <xsd:annotation>    <xsd:documentation>public enum TransactionType { JTA, RESOURCE_LOCAL };</xsd:documentation>   </xsd:annotation>  <xsd:restriction base="xsd:token">    <xsd:enumeration value="JTA" />     <xsd:enumeration value="RESOURCE_LOCAL" />   </xsd:restriction></xsd:simpleType>

?

当然,这时把persistence.xml中的“transaction-type”改成"RESOURCE_LOCAL",如下:

?

<persistence-unit name="IncidentTicketServicePU" transaction-type="RESOURCE_LOCAL">

?

再跑,数据成功插入数据库。

?

?

经过思考,我觉得问题的原因是这样的:首先,

在我的代码中使用了以下代码获得EntityManager实例:

?

EntityManagerFactory emf = Persistence.createEntityManagerFactory("IncidentTicketServicePU");EntityManager em = emf.createEntityManager();

?
之所以使用这种方式而没有使用@PersistenceContext注入EntityManager,是因为当时使用注入方式不成功。今天得知在POJO上是无法使用@PersistenceContext注入的,只能在ejb上使用,这就是为什么之前我使用注入失败的原因。


再回到原来的问题,用工厂方式获得EntityManager发生错误的原因是:用工厂方式获得的EntityManager的transaction实际上应该由应用程序自己管理,而非JTA管理。但是由于设置了transaction-type="JTA",实际上并没有任何代码负责对transaction的管理,而且在代码中手工管理transaction还会报错。要解决这个问题有两种方法:


1. 按照我上面描述的方法修改persistence.xml中的“transaction-type”并编写手工管理transaction的代码;

?

2. 不修改transaction-type="JTA",使用session bean,在session bean中使用@PersistenceContext注入EntityManager。这样在程序里不用自己控制transaction,直接persist就可以。


两种方式都可以正常运行,但是为了是代码的优雅,最终选择了第二种方法。

?

?


@Repository("customerDao")
class CustomerDAO{
@PersistenceContext
private EntityManager em;
...
}


在Service里:

@Service("customerService")
@Transactional
class CustomerService{
@Autowired
private CustomerDAO customerDao;

}

在Spring config file里:   

    <bean id="transactionManager"
        ref="entityManagerFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager" />   
    <bean id="txManager" ref="entityManagerFactory" />
</bean>
<bean />
<!-- persistence -->
<bean />



2 楼 sxitzmg 2011-12-16   感谢啊,困扰我48小数的bug解决了 3 楼 k1280000 2012-08-27   建议你看看这篇文字 http://wenku.baidu.com/view/34332f6327d3240c8447ef48.html

热点排行