我正在尝试使用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>
答案 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 中通过属性配置:
<jta-data-source>
元素请查看此答案以获取更多详细信息: https://stackoverflow.com/a/9137741/1980178
答案 2 :(得分:-1)
你确定你没有混合两个框架。 RecipeResource有一个来自JavaEE框架的@Path注释, @Transactional 注释来自Spring框架,我认为你应该用 @TransactionAttribute 替换它,这是等效的JavaEE anotation。
查看here以了解Spring和JavaEE中的事务之间的详细信息