您正在滥用CDI管理的bean作为业务服务。它没有交易管理的线索。您需要手动管理交易。因为通常这很麻烦,而且您显然使用的是Glassfish,它是支持EJB的完全有价值的Java
EE容器,所以您希望为此使用完全有价值的EJB。在
EntityManagerEJB内部使用时,容器将完全透明地管理数据库事务。一个EJB方法调用计为单个事务(即,当您触发多个数据库查询而其中一个失败时,所有内容将自动回滚)。
总的来说,您似乎混用了模型,控制器和服务的职责。也不要使您的实体成为托管bean。您还应该绝对不要在Javabean的getter方法中执行业务逻辑(例如
getBooks())。在迭代组件中引用时,将在每个迭代回合中调用它。因此,假设您有100条记录,那么数据库将被命中100次。这显然是低效的。
看起来应该像这样:
模型(实体):
@Entity@Table(name = "BOOKS")public class Book implements Serializable { // ...}
控制器(辅助bean):
@Named@RequestScopedpublic class BookController { private Book book; private List<Book> books; @EJB private BookService service; @PostConstruct public void init() { book = new Book(); books = service.list(); } public void add() { service.save(book); init(); } public Book getBook() { return book; } public List<Book> getBooks() { return books; }}
服务(EJB):
@Statelesspublic class BookService { @PersistenceContext private EntityManager em; public List<Book> list() { return em.createQuery("FROM Book", Book.class).getResultList(); } public Book find(Integer id) { return em.find(Book.class, id); } public Integer save(Book book) { em.persist(book); return book.getId(); } public void update(Book book) { em.merge(book); } public void delete(Book book) { em.remove(em.contains(book) ? book : em.merge(book)); }}
视图(Facelet;简化):
<h:inputText id="title" value="#{bookController.book.title}"/><h:inputText id="author" value="#{bookController.book.author}"/><h:inputText id="price" value="#{bookController.book.price}"/><h:commandButton value="Add" action="#{bookController.add}" />...<h:dataTable value="#{bookController.books}" var="book"> <h:column><f:facet name="header">ID</f:facet>#{book.id}</h:column> <h:column><f:facet name="header">Title</f:facet>#{book.title}</h:column> <h:column><f:facet name="header">Author</f:facet>#{book.author}</h:column> <h:column><f:facet name="header">Price</f:facet>#{book.price}</h:column></h:dataTable>
(您的编辑和删除按钮没有任何意义,因此我将其删除了,您可能希望将其放入数据表中)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)