我是 hibernate 的新手,我希望它通过 JNDI 使用来自应用程序服务器的数据库连接。
奇怪的是,它在数据库中创建了我的表,但不保存实体。看起来,它没有提交。
有没有人遇到过与 hibernate 类似的问题?
这是一个小测试 servlet:
public class WriteTest extends HttpServlet
{
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
/*try
{
User user = new User("Hans", "Maulwurf", "hans.maulwurf@test.de");
InitialContext ctx = new InitialContext();
UserFacadeBean bean = (UserFacadeBean) ctx.lookup("ejb/UserFacadeBeanService");
bean.persist(user);
}
catch (NamingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}*/
EntityManager em = JpaUtil.getEntityManagerFactory().createEntityManager();
//em.getTransaction().begin();
System.out.println("Begin transfer");
User user = new User("Hans", "Maulwurf", "hans.maulwurf@test.de");
Adress adress = new Adress("Deppenstraße 3","Deppingen");
//user.setAddress(adress);
System.out.println("Save User 'Hans Maulwurf'");
em.persist(user);
//em.persist(adress);
//em.getTransaction().commit();
em.close();
System.out.println("Everything went better than expected!");
}
}
这是小助手类:
public class JpaUtil
{
private static final EntityManagerFactory emf;
static
{
try
{
System.out.println("Initialize EntityManagerFactory...");
emf = Persistence.createEntityManagerFactory("testPU");
}
catch (Throwable ex)
{
System.err.println("Initial EntityManagerFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static EntityManagerFactory getEntityManagerFactory()
{
return emf;
}
}
我的用户对象:
@Entity
@Table(name = "T_UserJpa")
public class User implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Embedded
@AttributeOverrides(
{
@AttributeOverride(name = "street", column =
@Column(name = "user_street")),
@AttributeOverride(name = "city", column =
@Column(name = "user_city", length = 50))
})
private Adress adress;
private String firstname;
private String lastname;
private String email;
public User()
{
}
public User(String firstname, String lastname, String email)
{
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Adress getAddress()
{
return adress;
}
public void setAddress(Adress adress)
{
this.adress = adress;
}
public String getFirstname()
{
return firstname;
}
public void setFirstname(String firstname)
{
this.firstname = firstname;
}
public String getLastname()
{
return lastname;
}
public void setLastname(String lastname)
{
this.lastname = lastname;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (!(obj instanceof User))
{
return false;
}
final User user = (User) obj;
return !(email != null ? !email.equals(user.email) : user.email != null);
}
@Override
public int hashCode()
{
return 29 * (email != null ? email.hashCode() : 0);
}
}
我的 persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="testPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/testdb</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.connection.autocommit" value="true"/>
</properties>
</persistence-unit>
</persistence>
编辑:我忘了说,我已经使用了这个线程中提供的信息:Learning resource for Configuring Hibernate JPA 2.0 on Glassfish server
最佳答案
在应用程序服务器中,您可以让容器管理 EntityManager
(也称为持久性上下文)或让应用程序管理 EntityManager
。在这两种情况下,您都必须将持久性上下文与作为 JTA 事务或普通 JDBC 事务的事务相关联。
关于您手头的问题,应考虑以下几点:
- 您的
persistence.xml
文件表明您打算使用 JTA 数据源,因此使用 JTA 事务来执行事务性工作。 - 此外,您的
JpaUtil
类负责创建应用程序管理的EntityManager
实例。
根据以上两个陈述和您的应用程序所展示的行为,您的 EntityManager
实例似乎没有与 JTA 事务相关联。因此,在持久性上下文中所做的任何更改都不会刷新到数据库中。这仅仅是因为 JPA 提供者将依赖 JTA 事务和征用的资源来执行事务性工作;如果没有找到,则不会完成任何工作(与资源本地事务的情况不同,其中连接池和资源登记由 JPA 提供程序本身执行)。
因此,在对实体执行任何更改之前,EntityManager
或持久性上下文必须与 Activity 事务相关联,以便对持久性上下文中的实体所做的所有更改可以刷新到数据库。要解决您的问题,您必须:
开始一个新的 JTA 事务。您可以选择容器管理的事务或应用程序管理的事务。
- 顾名思义,容器管理事务完全由容器管理。您不能调用 API 来启动和终止此类交易。相反,您必须在 EJB 中执行所有事务性工作。所讨论的 EJB 应该配置为需要容器管理事务的 EJB。在您的场景中演示如何使用 EJB 执行事务性工作超出了此答案的范围。如果您还没有学会如何编写 EJB,我建议您阅读 EJB。
应用程序或 Bean 管理的事务由应用程序本身管理,并且 不是靠容器。虽然这可能适合您的情况,但请注意您现在负责事务管理;这种策略通常会导致错误,而且开发人员往往没有很好地理解它,因此在大多数项目中它通常被认为是一种不好的做法。如果您希望使用 Bean 管理的事务,那么您将需要使用
UserTransaction
启动一个事务。 API类如下图:public class WriteTest extends HttpServlet { @Resource UserTransaction tx; // a UserTransaction reference is injected like a any other resource. It can also be looked up from JNDI. public void doGet(HttpServletRequest request, HttpServletResponse response) { ... tx.begin(); // Start a new JTA BMT EntityManager em = JpaUtil.getEntityManagerFactory().createEntityManager(); ... User user = new User("Hans", "Maulwurf", "hans.maulwurf@test.de"); Adress adress = new Adress("Deppenstraße 3","Deppingen"); //user.setAddress(adress); em.persist(user); em.close(); ... tx.commit(); // Commit the JTA BMT } }
上面的代码并不完全适合生产。例如,它不执行任何异常处理,也不会在应用程序出现故障时显式回滚更改。
如果
EntityManager
尚未与 JTA 事务关联,则将EntityManager
实例加入 JTA 事务。如果您先启动 JTA 事务(在上面涉及 Bean 托管事务的示例中完成),则没有必要这样做,但是如果您首先使用JpaUtil
类创建EntityManager
,然后再开始交易,那么你必须使用EntityManager.joinTransaction()
将持久性上下文与 JTA 事务连接起来的方法。很明显,任何从与事务无关的持久性上下文中刷新的更改都将被忽略。
关于java - 使用 JTA 和 Glassfish Application Server 的 Hibernate JPA 似乎没有提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6895868/