2014-10-02 194 views
1

我正尝试使用JPA在Java Web应用程序中实现RESTful WebService的持久性。程序通过EntityManager运行,持久化一个Entity类,被一个事务包围(开始和提交)。交易虽然麻烦。当我检查MySQL数据库时,创建了必要的表格,但其中没有条目。怎么可能?代码中出现了什么问题?EntityManager不会坚持实体类?

我的服务类:

@Stateless 
public class ReportService { 
    @PersistenceContext(unitName = "AbcPU") // default type is PersistenceContextType.TRANSACTION 
    EntityManager em; 

    public void saveDog() { 
     System.out.println("BBBBB Start ReportService.saveDog();"); 
     Doggy doggy = new Doggy(); 
     doggy.setDogName("Wuffi"); 
     try { 
      System.out.println("BBBBB Persist Success ReportService.saveDog();"); 
      em.getTransaction().begin(); 
      em.persist(doggy); 
      em.flush(); 
      em.getTransaction().commit(); 
     } catch (Exception ex) { 
      System.out.println("BBBBB Persist Fail ReportService.saveDog();"); 
      System.err.println("Error with em.persist(doggy): " + ex.getMessage()); 
     } 
     System.out.println("BBBBB Stop ReportService.saveDog();"); 
    } 
} 

我的资源类:

@Path("report") 
@Produces(MediaType.APPLICATION_JSON) 
public class ReportResource { 
    @EJB 
    private ReportService rs; 

    @GET 
    public Response findReports() { 
     final List<Report> reports = rs.findAllReports(); 

     System.out.println("AAAAA Start rs.saveDog();"); 
     rs.saveDog(); 
     System.out.println("AAAAA Stop rs.saveDog();"); 

     return Response.ok(new GenericEntity<List<Report>>(reports) {}) 
         .build(); 
    } 
} 

我的实体类:

@Entity 
public class Doggy implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @NotNull 
    private String dogName; 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getDogName() { 
     return dogName; 
    } 

    public void setDogName(String dogName) { 
     this.dogName = dogName; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Doggy)) { 
      return false; 
     } 
     Doggy other = (Doggy) object; 
     if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "com.glasses.pandora.domain.Doggy[ id=" + id + " ]"; 
    } 
} 

我的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="AbcPU" transaction-type="JTA"> 
    <jta-data-source>java:/jdbc/abc</jta-data-source> 
    <exclude-unlisted-classes>false</exclude-unlisted-classes> 
    <properties> 
     <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/> 
    </properties> 
    </persistence-unit> 
</persistence> 

我的Maven依赖在pom.xml:

01:58:54,158 INFO [stdout] (default task-23) AAAAA Start rs.saveDog(); 
01:58:54,160 INFO [stdout] (default task-23) BBBBB Start ReportService.saveDog(); 
01:58:54,160 INFO [stdout] (default task-23) BBBBB Persist Success ReportService.saveDog(); 
01:58:54,160 INFO [stdout] (default task-23) BBBBB Persist Fail ReportService.saveDog(); 
01:58:54,161 ERROR [stderr] (default task-23) Error with em.persist(doggy): A JTA EntityManager cannot use getTransaction() 
01:58:54,161 INFO [stdout] (default task-23) BBBBB Stop ReportService.saveDog(); 
01:58:54,162 INFO [stdout] (default task-23) AAAAA Stop rs.saveDog(); 

MySQL的节目表:

其运行后
<dependencies> 
    <dependency> 
     <groupId>mysql</groupId> 
     <artifactId>mysql-connector-java</artifactId> 
     <version>5.1.32</version> 
    </dependency> 
    <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-entitymanager</artifactId> 
     <version>4.3.1.Final</version> 
     <scope>provided</scope> 
    </dependency> 
    <dependency> 
     <groupId>unknown.binary</groupId> 
     <artifactId>hibernate-jpamodelgen-4.3.1.Final</artifactId> 
     <version>SNAPSHOT</version> 
     <scope>provided</scope> 
    </dependency> 
    <dependency> 
     <groupId>javax</groupId> 
     <artifactId>javaee-web-api</artifactId> 
     <version>7.0</version> 
     <scope>provided</scope> 
    </dependency> 
</dependencies> 

我的控制台输出

mysql> show tables; 
+--------------------+ 
| Tables_in_abc  | 
+--------------------+ 
| Doggy    | 
| hibernate_sequence | 
+--------------------+ 
2 rows in set (0.00 sec) 

mysql> SELECT * FROM Doggy; 
Empty set (0.00 sec) 

mysql> 
+0

删除'和'@ Stateful'将它改为@Stateless。在ReportResource中将'@ Inject'更改为'@ EJB'作为'ReportService'字段。正确定义。 – Gas 2014-10-02 21:05:18

+0

嘿嘿!谢谢您的帮助!我试图通过直接在Wildfly中创建MySQL数据源来追随您的领先地位。测试工作正常,现在创建表格。但是EntityManager仍然不能坚持。任何想法为什么? – Socrates 2014-10-03 17:11:16

回答

1

有几个问题。首先,hwellmann提到,你没有指定数据源。 JTA要求使用与JTA事务相关的连接。

第二个是你似乎没有在事务中包装saveDog方法。坚持调用只会将实体注册到上下文中;它只在关联的事务提交时被插入到数据库中,或者调用EntityManager.flush()。如果您在保存方法中调用em.flush,这将验证您的EntityManager与交易正确关联,并且插入成功。

-2

我敢肯定你需要查找您的持久性上下文并从中分配实体管理器。

@Dependent 
@Stateful 
public class ReportService { 
    @PersistenceContext(name = "persistence/AbcPU", unitName = "AbcPU") 

    public abstract EntityManager getEntityManager() { 
     EntityManager em = null; 
     try { 
      Context envCtx = InitialContext.doLookup("java:comp/env"); 
      em = (EntityManager) envCtx.lookup("persistence/AbcPU"); 
     } catch (NamingException ne) { 
      //Handle Exception 
     } 
     return em; 
    } 

    public void saveDog() { 
     System.out.println("BBBBB Start ReportService.saveDog();"); 
     Doggy doggy = new Doggy(); 
     doggy.setDogName("Wuffi"); 
     try { 
      System.out.println("BBBBB Persist Success ReportService.saveDog();"); 
      getEntityManager().persist(doggy); 
     } catch (Exception ex) { 
      System.out.println("BBBBB Persist Fail ReportService.saveDog();"); 
      System.err.println("Error with em.persist(doggy): " + ex.getMessage()); 
     } 
     System.out.println("BBBBB Stop ReportService.saveDog();"); 
    } 
} 
+0

要么做老派的JNDI查找,要么使用资源注入。混合两者都没有意义。这并不能解释为什么交易似乎不起作用。 – 2014-10-02 18:31:14

+0

@hwellmann这是如何混合JNDI查找和资源注入? – 2014-10-02 18:33:49

1

检查服务器日志以查看您的应用程序确实正在使用MySQL数据源还是嵌入式默认H2数据源。

您的persistence.xml不包含<jta-data-source>,所以我会说默认数据源正在使用。

查看Wiki文章关于Datasource Configuration

+0

嘿hwellmann!谢谢你的帮助。我根据Gas的意见和建议更改了代码,并且我还直接在Wildfly中创建了数据源。现在在数据库中创建表,但EntityManager仍然无法保留。任何想法为什么? – Socrates 2014-10-03 17:13:15

1

看看这个错误 - Error with em.persist(doggy): A JTA EntityManager cannot use getTransaction()。 EJB是自动处理事务 - 删除您ReportService的em.getTransaction().begin()em.flush();em.getTransaction().commit();

你的方法,下面应该是这样的:从你的`ReportService`和@ Dependent`

public void saveDog() { 
     System.out.println("BBBBB Start ReportService.saveDog();"); 
     Doggy doggy = new Doggy(); 
     doggy.setDogName("Wuffi"); 
     try { 
      System.out.println("BBBBB Persist Success ReportService.saveDog();"); 
      em.persist(doggy); 
     } catch (Exception ex) { 
      System.out.println("BBBBB Persist Fail ReportService.saveDog();"); 
      System.err.println("Error with em.persist(doggy): " + ex.getMessage()); 
     } 
     System.out.println("BBBBB Stop ReportService.saveDog();"); 
    } 
+0

上帝该死! ^^它工作!最后!天然气,你是上帝!实际上你们都是!非常感谢!你让我今天一整天都感觉很好! :) – Socrates 2014-10-03 17:52:47

+0

@ user3164889很高兴工作;-) – Gas 2014-10-03 18:20:25