我是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
答案 0 :(得分:6)
在应用程序服务器中,您可以拥有一个托管EntityManager
的容器(也称为持久化上下文)或托管的应用程序EntityManager
。在这两种情况下,您都必须将持久性上下文与作为JTA事务或纯JDBC事务的事务关联。
关于你手头的问题,应该考虑以下几点:
persistence.xml
文件表明您打算使用JTA数据源,因此需要使用JTA事务来执行事务性工作。JpaUtil
班级负责创建应用程序管理的EntityManager
个实例。根据上述两个语句以及您的应用程序演示的行为,您的EntityManager
实例似乎与JTA事务无关。因此,在持久化上下文中进行的任何更改都不会刷新到数据库。这仅仅是因为JPA提供者将依赖JTA事务和登记资源来执行事务性工作;如果没有找到,则不会进行任何工作(与资源本地事务的情况不同,其中连接池和资源登记由JPA提供者本身执行)。
因此,在对实体执行任何更改之前,EntityManager
或持久性上下文必须与活动事务关联,以便可以刷新对持久性上下文中的实体所做的所有更改到数据库。要解决您的问题,您必须:
开始新的JTA交易。您可以选择容器管理的事务或应用程序管理的事务。
应用程序或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管理事务的示例中完成),但是如果首先使用EntityManager
类创建JpaUtil
,然后启动事务,则不需要这样做之后,您必须使用EntityManager.joinTransaction()
方法将持久性上下文与JTA事务连接起来。很明显,从与事务无关的持久化上下文中刷新的任何更改都将被忽略。
答案 1 :(得分:3)
您应该使用容器提供的事务支持。这是Pro JPA 2掌握Java Persistence API一书中的示例。我希望这会有所帮助:
public class EmployeeServlet extends HttpServlet {
@PersistenceUnit(unitName="EmployeeService")
EntityManagerFactory emf;
@Resource UserTransaction tx;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
int id = Integer.parseInt(request.getParameter("id"));
String name = request.getParameter("name");
long salary = Long.parseLong(request.getParameter("salary"));
tx.begin();
EntityManager em = emf.createEntityManager();
try {
EmployeeService service = new EmployeeService(em);
service.createEmployee(id, name, salary);
} finally {
em.close();
}
tx.commit();
// ...
}
}
答案 2 :(得分:1)
本指南适用于在NetBeans.8.0 IDE中集成hibernate.4.3.5和EJB以及JTA和GlassFish.4.0。在net bean中创建一个web项目(注意:不要使用maven制作web项目因为Netbeans.8.0 IDE中存在错误)并将hibernate jar文件添加到项目中,其他与配置MySql和glassfish相关的设置非常简单(Just在参考资料中定义连接池和JDBC&gt; JDBC:JDBC连接池和JDBC资源,如果你搜索它,可以在网上找到指导)(注意:为了定义一个正确的JNDI,首先创建一个依赖于JNDI的临时项目在glassfish中的JPA项目,然后复制Glassfish中为此项目创建的设置,因为如果您在创建第一个连接池时,如果您在glassfish中自己创建第一个连接池,那么在glassfish中会出现一个错误。所以我在本文中没有描述然后创建persistence.xml文件,如下所示:
<persistence-unit name="omidashouriPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/yourJNDI (which you defined in glassfish) </jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/YourSchemaName"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="yourpassword"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
在您的EJB类(使用@Stateless注释的类)中创建EntityManager时使用以下语法:
@PersistenceContext(unitName = " omidashouriPU ")
EntityManager em;
em.persist(YourEntityObject);
如您所知,当您使用“transaction-type =&#34; JTA&#34 ;,交易管理不在您手中时,意味着,管理开启和关闭交易是应用服务器(Here GlassFish)的责任。实际上,如果你在模式设计中检查你的persistence.xml,在持久性提供程序下拉框前面你可以看到现在添加了hibernate。
答案 3 :(得分:0)
当您提交更改时,即取消注释提交行时,它是否会提交?
同时尝试通过
检查您的配置toggleAutoCommit = session.connection()。getAutoCommit();