事务性CDI bean不向数据库提交记录

时间:2017-01-07 20:57:07

标签: jpa java-ee cdi

我正在尝试使用JAX-RS构建一个简单的REST服务,它将在数据库表上执行标准的CRUD操作。我能够成功查询记录,但我无法插入新的记录。我没有得到任何错误,当我在调试模式中逐步执行代码时,一切看起来都不错。我正在使用在Glassfish 4.1容器中运行的事务性CDI bean。

感觉它只是从不提交交易。我对Java EE很陌生,但我的理解是,由于bean是事务性的,容器应该为我处理提交。有人知道为什么不是吗?

@Path("/recipes")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class RecipeResource {
    @Inject
    RecipesService recipesService;

    @GET
    public List<Recipe> getRecipes() {
        return recipesService.getAllRecipes();
    }

    @POST
    public void addRecipse(Recipe recipe) {
        recipesService.addRecipe(recipe);
    }

}

public class RecipesService {
    @PersistenceContext(unitName="PANTRYDB", type=PersistenceContextType.TRANSACTION)
    EntityManager em;

    public RecipesService () {

    }

    public List<Recipe> getAllRecipes () {
        List<Recipe> recipes = null;

        try {
            TypedQuery<Recipe> typedQuery = em.createQuery("select r from Recipe r", Recipe.class);

            recipes = typedQuery.getResultList();
        } catch (Exception e) {
            System.out.println(e);
        }

        return recipes;
    }

    @Transactional
    //This is the method that seems to not commit it's transaction
    //The Recipe object is populated correctly, and the persist() doesn't 
    //throw any errors
    public void addRecipe(Recipe recipe) {
        try {
            em.persist(recipe);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

@Entity
@Table(name="RECIPES", schema="COOKBOOK")
public class Recipe {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    @Column
    private String name;

    @Column(name="CREATED_DATE")
    private Calendar createdDate;

    @Column(name="LAST_MADE_DATE")
    private Calendar lastMadeDate;

    @Column
    private String description;

    @Column
    private String notes;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Calendar getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Calendar createdDate) {
        this.createdDate = createdDate;
    }

    public Calendar getLastMadeDate() {
        return lastMadeDate;
    }

    public void setLastMadeDate(Calendar lastMadeDate) {
        this.lastMadeDate = lastMadeDate;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    @Override
    public String toString() {
        return name;
    }
}

的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="PANTRYDB" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.domain.Recipe</class>
        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />      
            <property name="javax.persistence.jdbc.url" value="jdbc:derby:/Users/development/eclipse/ws_playground/databases/pantry_db/PANTRYDB" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
            <property name="javax.persistence.jdbc.user" value=""/>
            <property name="javax.persistence.jdbc.password" value=""/>
        </properties>
    </persistence-unit>
</persistence>

3 个答案:

答案 0 :(得分:1)

我在weblogic 12.2.1上尝试了你的应用程序并成功插入数据库,我对事务没有任何问题。

这是我的代码。

RecipeResource类(我修改了@Path以通过网络浏览器调用它,并且还手动实例化Recipe

@Path("/recipes")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)

public class RecipeResource {

    @Inject
    RecipesService recipesService;

    @GET
    @Path("get")
    public List<Recipe> getRecipes() {
        return recipesService.getAllRecipes();
    }

    @GET
    @Path("add")
    public String addRecipse() {
        Recipe recipe = new Recipe();
        recipe.setDescription("desc");
        recipesService.addRecipe(recipe);
        return "OK";
    }

}

Recipe类和你的类相同,只不过我评论了架构:

@Entity
@Table(name="RECIPES") //, schema="COOKBOOK")
public class Recipe {
}

我的persistence.xml(我正在使用内存数据库):

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns    /persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">

   <persistence-unit name="PANTRYDB" transaction-type="JTA">
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/__default</jta-data-source>
    <class>org.jvi.webservice.transactional.db.Recipe</class>
    <properties>
        <!--<property name="eclipselink.ddl-generation" value="create-tables"/>-->
        <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
        <property name="eclipselink.logging.level" value="FINE"/>
        <property name="eclipselink.logging.level.sql" value="FINE"/>
        <property name="eclipselink.logging.parameters" value="true"/>
        <property name="eclipselink.logging.logger" value="DefaultLogger"/>
        <property name="eclipselink.cache.shared.default" value="false"/>
    </properties>
</persistence-unit>

所以你的问题可能来自Application Server。

您是否尝试在其他服务器上部署webapp?

答案 1 :(得分:0)

当您使用JTA事务管理时,应用程序服务器提供了创建和管理数据库连接的责任,而不是您的应用程序。

基本上,您必须在GlassFish服务器实例中配置数据源,而不是直接在 persistence.xml 中通过属性配置:

  1. 在GlassFish服务器实例中配置连接池数据源JNDI名称
  2. 通过<jta-data-source>元素
  3. 在persistence.xml中链接数据源配置

    请查看此答案以获取更多详细信息: https://stackoverflow.com/a/9137741/1980178

答案 2 :(得分:-1)

你确定你没有混合两个框架。 RecipeResource有一个来自JavaEE框架的@Path注释, @Transactional 注释来自Spring框架,我认为你应该用 @TransactionAttribute 替换它,这是等效的JavaEE anotation。

查看here以了解Spring和JavaEE中的事务之间的详细信息