我这两天刚开始使用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就可以。
两种方式都可以正常运行,但是为了是代码的优雅,最终选择了第二种方法。
分享到:
相关推荐
1. **增加(Create)**: 创建一个新的实体实例,然后调用`EntityManager.persist()`方法将其保存到数据库。 ```java EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit"); ...
- **持久化(Persist)**:使用 `entityManager.persist(entity)` 方法将新实体保存到数据库。 - **查找(Find)**:通过 `entityManager.find(Entity.class, id)` 可以根据实体类和主键找到对应的实体。 - **更新...
在这里,我们需要指定持久化单元(Persistence Unit)的名称,使用的JPA提供商,以及连接到数据库的相关属性。 3. **使用EntityManager**:JPA的核心接口,通过EntityManager我们可以执行CRUD(Create, Read, ...
**Entity Manager(实体管理器)** 是JPA的核心组件,它维护了实体对象的状态,并负责将这些对象保存到数据库或从数据库加载它们。`EntityManager`提供了方法如`persist()`, `merge()`, `remove()`, `find()`等来...
1. 插入(Persist):使用`entityManager.persist(entity)`将新对象保存到数据库。 2. 更新(Merge):如果实体已经存在数据库中,`entityManager.merge(entity)`会更新其状态。 3. 删除(Remove):`...
例如,创建一个新的`Person`对象并将其保存到数据库: ```java public void save() { Person person = new Person("aaa", 121); entityManager.persist(person); } ``` 这段代码首先创建了一个新的`Person`实例...
- **保存(Persist)**: 使用`entityManager.persist(entity)`将新实体保存到数据库。 - **加载(Find)**: 通过`entityManager.find(Entity.class, id)`获取指定ID的实体。 - **更新(Merge)**: `entityManager....
- **创建(Create)**:使用`entityManager.persist(entity)`将新实体保存到数据库。 - **读取(Read)**:通过`entityManager.find(Class<T> entityClass, ID id)`方法查找特定ID的实体。 - **更新(Update)**...
当实体处于持久化状态时,任何改变都会自动同步到数据库。通过`entityManager.persist()`方法可将瞬态对象变为持久态。已持久化的对象,其属性更改后调用`entityManager.flush()`会触发更新。 #### 3.2 merge()方法...
- Create:JPA通过`EntityManager.persist()`方法将新建的对象保存到数据库中。 - Read:`EntityManager.find()`或JPQL(Java Persistence Query Language)查询语言用于获取数据库中的数据。 - Update:更新操作...
创建操作(Create):使用`EntityManager`的`persist()`方法将新实体保存到数据库。 ```java EntityManager entityManager = entityManagerFactory.createEntityManager(); EntityTransaction tx = entityManager....
例如,你可以使用`entityManager.persist()`来保存新实体,`entityManager.find()`来查找实体,`entityManager.merge()`来更新实体,以及`entityManager.remove()`来删除实体。EntityManager还提供了事务管理和查询...
2. **保存实体(Persist)**: 使用`EntityManager.persist(entity)`方法将新实体保存到数据库,如果实体已经存在,此操作会更新对应的数据库记录。 3. **查找实体(Find)**: `EntityManager.find(Class entity...
在JPA中创建实体非常直观,可以通过构造器或setter方法设置实体属性,然后通过`EntityManager`的`persist()`方法将实体持久化到数据库中。例如,对于一个名为`User`的简单实体: ```java User user = new User(); ...
- `entityManager.persist(entity)`:将对象持久化到数据库。 - `entityManager.find(Entity.class, id)`:根据ID查找对象。 - `entity.setProperty(value)` 和 `entityManager.merge(entity)`:更新对象。 - `...
4. **更新(Merge)**: `EntityManager.merge()`方法将一个脱离管理的实体合并到当前的实体管理器上下文中,然后持久化到数据库。 5. **删除(Remove)**: `EntityManager.remove()`方法用来删除一个持久化实体,它...
1. **实体类与表映射**:在`Order`类中,我们可以使用`@Entity`注解标识这是一个JPA实体,`@Table(name = "orders")`注解指定它映射到数据库中的`orders`表。此外,类的属性可能使用`@Id`、`@GeneratedValue`等注解...
- 插入(Persist):调用`entityManager.persist(entity)`将新实体保存到数据库。 - 更新(Merge):`entityManager.merge(entity)`用于更新现有实体。 - 删除(Remove):`entityManager.remove(entity)`从...
1. **保存(Save)**:使用EntityManager的persist()方法保存新实体,或merge()方法更新已存在的实体。 2. **删除(Delete)**:调用remove()方法删除实体,实体必须是管理状态的。 3. **加载(Load)**:find()...
使用Hibernate JPA,开发者可以利用其强大的ORM(Object-Relational Mapping)能力,将Java对象直接映射到数据库表。 6. **Restful API** Restful API是一种Web服务设计模式,通过HTTP方法(GET, POST, PUT, ...