您好我创建了一个简单的JSF
+ JPA
应用程序。我的网络应用包含Entity
,ManagedBean
和部分JSF
页面。它的目的是在MySQL数据库中创建和存储一个对象。每次我想将实体持久存入javax.persistence.TransactionRequiredException
时,我都会PersistenceContxt
。但是,当将UserTransaction
注入控制器类时,它可以正常工作,但我不明白为什么?因为它应该不需要添加UserTransaction
,因为它是容器管理的。我错了还是什么?或者我的代码中还有其他问题?
这是我的ManagedBean代码:
@ManagedBean
@SessionScoped
public class Controller {
@PersistenceContext
private EntityManager em;
private Book book;
public Controller() {}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public String createBook() {
book = new Book();
return "create";
}
public String showResponse() {
em.persist(book);
return "response";
}
}
以下是create.xhtml
facelet:
...
<h:form>
<h:panelGrid columns="2">
<h:outputText>Title</h:outputText>
<h:inputText value="#{controller.book.title}" />
</h:panelGrid>
</h:commandButton action="#{controller.showResponse()}" value="Response" />
...
这是Persistence.xml
内容:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="JPATestPU" transaction-type="JTA">
<jta-data-source>jdbc/mysql</jta-data-source>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
</persistence-unit>
</persistence>
答案 0 :(得分:2)
仅针对EJB中的方法自动创建事务,而不是针对管理的bean。 如果您在JEE7容器中,可以尝试将@Transactional添加到Controller托管bean,否则您需要使用UserTransation来管理事务。
以下是我使用的一段代码:
@Transactional
public class PersonService {
@PersistenceContext
private EntityManager em;
public void savePerson(Person person) {
em.persist(person);
}
我从servlet调用它:
@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
@Inject
PersonService service;
....
service.savePerson(p);
System.out.println("Person saved");
我可以在数据库中看到它已保存,在日志中我看到以下消息:
INFO: Managed bean with Transactional annotation and TxType of REQUIRED called outside a transaction context. Beginning a transaction...
INFO: Person saved
因此,您可以看到新事务被装箱并保存对象
答案 1 :(得分:0)
查看了代码段。我认为这是一个设计问题,而不是技术问题。我建议你应该考虑如下构建你的应用程序: 1.数据库层 - MySql。 2.实体包 - 包含直接映射到数据库表的实体对象。 3.数据访问对象包 - 包含EJB(例如@Singleton,@ Stateless,@ Stateful)。 4. Controller Package - 包含表示层通过EL访问的servlet和/或托管bean(例如@ Natamed,@ ContextScoped,@ ManagedBean等) 5.表示层 - JSF页面(例如index.xhtml等)
以这种方式构建代码非常重要,因为事务和安全性以及其他服务是为EJB自动提供的,这是应该执行持久性的地方。也就是说,应该在不在Managed Beans对象中的EJB中引用EntityManager(通过@PersistenceContext)。控制器中的对象应使用@Inject(@EJB)注释来注入依赖项。
答案 2 :(得分:0)
除非您的操作是从数据库中读取,否则您需要的只有一件事是&#34; @Transactional&#34;方法上方的注释。您也可以在课程上方定义它。 但它不是合适的架构。至少你必须创建另一个类并将其注入你的bean。
如果您使用的是JavaEE,则应使用EJB。这很简单,您不必担心交易。容器可以控制整个事物。