2014-10-02 193 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