2014-10-02 3 views
1

Я пытаюсь использовать JPA для сохранения в веб-приложении Java для RESTful WebService. Программа проходит через EntityManager, сохраняя класс Entity, окруженный bz транзакцией (begin and commit). Однако транзакция вызывает проблемы. Когда я проверяю базу данных 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:

<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> 

Мой вывод на консоль после запуска:

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 показать таблицы:

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

Remove '@ Dependent' и' @ Stateful' из вашего 'ReportService' и измените его на @Stateless. В 'ReportResource' измените' @ Inject' на '@ EJB' для поля' ReportService'. Правильно определите . – Gas

+0

Эй, газ!Спасибо за помощь! Я попытался следовать вашему примеру, создав источник данных MySQL непосредственно в Wildfly. Тест работает отлично, и таблицы теперь создаются. Но EntityManager все еще не может сохраняться. Любая идея почему? – Socrates

ответ

1

Есть несколько проблем. Первый, упомянутый hwellmann, заключается в том, что вы не указали источник данных. JTA требует так, чтобы были использованы соединения, связанные с транзакцией JTA.

Во-вторых, вы, похоже, не завернули метод saveDog в транзакции. Постоянный вызов будет регистрировать только Entity с контекстом; он вставляется только в базу данных при совершении связанной транзакции или вызывается 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, либо используете инъекцию ресурсов. Смешать оба. И это не объясняет, почему транзакции не работают. –

+0

@hwellmann Как это смешение JNDI-поиска и впрыска ресурсов? –

1

Проверьте логи сервера, чтобы увидеть, если ваше приложение действительно с помощью источника данных MySQL или встроенный источник данных по умолчанию H2.

Ваш persistence.xml не содержит <jta-data-source>, поэтому я бы сказал, что используется источник данных по умолчанию.

См. Статью в Wiki около Datasource Configuration.

+0

Эй, Хельманн! Спасибо за вашу помощь. Я изменил код в соответствии с Gas и вашими советами, и я также создал источник данных прямо в Wildfly. Таблицы теперь создаются в базе данных, но EntityManager по-прежнему не может сохраняться. Любая идея почему? – Socrates

1

Посмотрите на ошибку - Error with em.persist(doggy): A JTA EntityManager cannot use getTransaction(). EJB автоматически обработки транзакций - удалите следующие из вашего ReportService em.getTransaction().begin(), em.flush(); и em.getTransaction().commit();

Ваш метод должен быть, как это:

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

+0

@ user3164889 Рад, что это сработало ;-) – Gas

Смежные вопросы