Java Eclipselink JPA、Oracle、Weblogic、Calling Persist 不提交到数据库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2004608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:22:49  来源:igfitidea点击:

Eclipselink JPA, Oracle, Weblogic, Calling Persist does not commit to database

javajpapersistenceeclipselink

提问by MJ.

I'm just starting to take a look at java persistence (at the moment with eclipse's default provider of eclipselink). Basically just creating an object and attempting to persist it to the db (Oracle). It was my understanding that the default transactionality should commit the new object to the database when the method returns but nothing seems to be happening. Any ideas?

我刚刚开始研究 java 持久性(目前使用 eclipse 的默认 eclipselink 提供程序)。基本上只是创建一个对象并尝试将其持久化到数据库(Oracle)。我的理解是,默认事务性应该在方法返回时将新对象提交到数据库,但似乎什么也没发生。有任何想法吗?

@Stateless
public class RegisterUser implements RegisterUserLocal {

 @PersistenceContext
 private EntityManager entityManager;

    public void registerNewUser(String username, String password){
     User user = new User();
     user.setPassword(password);
     user.setUsername(username);
     entityManager.persist(user);
     entityManager.getTransaction().commit();
    }
}

Persistence.xml:

持久性.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 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_1_0.xsd">
 <persistence-unit name="SCBCDEntities" transaction-type="RESOURCE_LOCAL">
  <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
  <class>examples.persistence.User</class>
  <properties>
   <property name="eclipselink.target-server" value="WebLogic_10"/>
   <property name="eclipselink.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
   <property name="eclipselink.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:db4"/>
   <property name="eclipselink.jdbc.user" value="SCBCD"/>
   <property name="eclipselink.jdbc.password" value="123456"/>
   <property name="eclipselink.logging.level" value="FINEST"/>
  </properties>
 </persistence-unit>
</persistence>

Entity Class:

实体类:

@Entity
@Table(name="USERS")
public class User implements Serializable {
 private static final long serialVersionUID = 1L;

 @Id
 private String username;

 private String password;

    public User() {
    }

 public String getUsername() {
  return this.username;
 }

 public void setUsername(String username) {
  this.username = username;
 }

 public String getPassword() {
  return this.password;
 }

 public void setPassword(String password) {
  this.password = password;
 }

}

Also, to respond to replies to this question, with the code I've listed the logs show a commit executing (some detail removed for brevity)

此外,为了回复对这个问题的回复,我列出的代码显示了提交执行(为了简洁起见,删除了一些细节)

[EL Finest]: 2010-01-05 22:58:07.468--UnitOfWork(25499586)--Thread(Thread[[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.
Default (self-tuning)',5,Pooled Threads])--PERSIST operation called on: examples.persistence.User@191ed96.
<Jan 5, 2010 10:58:07 PM EST> <Debug> <JTA2PC> <BEA-000000> <BEA1-001959ECF50B251A451D: [EJB examples.session.stateless.RegisterUs
er.registerNewUser(java.lang.String,java.lang.String)]: ServerTransactionImpl.commit()>
<Jan 5, 2010 10:58:07 PM EST> <Debug> <JTA2PC> <BEA-000000> <BEA1-001959ECF50B251A451D: [EJB examples.session.stateless.RegisterUs
er.registerNewUser(java.lang.String,java.lang.String)]: TX[BEA1-001959ECF50B251A451D] active-->pre_preparing
<Jan 5, 2010 10:58:07 PM EST> <Debug> <JTA2PC> <BEA-000000> <SC[mr_domain+AdminServer] active-->pre-preparing
er.registerNewUser(java.lang.String,java.lang.String)]: TX[BEA1-001959ECF50B251A451D] prepared-->committing
<Jan 5, 2010 10:58:07 PM EST> <Debug> <JTA2PC> <BEA-000000> <SC[mr_domain+AdminServer] pre-prepared-->committed
er.registerNewUser(java.lang.String,java.lang.String)]: TX[BEA1-001959ECF50B251A451D] committing-->committed
...
...

but if I add 'flush' after the persist, I get 'notransaction'...

但是如果我在坚持之后添加“flush”,我会得到“notransaction”......

[EL Finest]: 2010-01-05 22:44:55.218--UnitOfWork(113017)--Thread(Thread[[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.De
fault (self-tuning)',5,Pooled Threads])--PERSIST operation called on: examples.persistence.User@1717dea.
<Jan 5, 2010 10:44:55 PM EST> <Info> <EJB> <BEA-010227> <EJB Exception occurred during invocation from home or business: weblogic.
ejb.container.internal.StatelessEJBLocalHomeImpl@1509b8 threw exception: javax.persistence.TransactionRequiredException:
Exception Description: No transaction is currently active>
<Jan 5, 2010 10:44:55 PM EST> <Debug> <JTA2PC> <BEA-000000> <BEA1-001859ECF50B251A451D: [EJB examples.session.stateless.RegisterUs
er.registerNewUser(java.lang.String,java.lang.String)]: TX[BEA1-001859ECF50B251A451D] active-->rolling back
...
...

采纳答案by MJ.

After much investigation, including trying both container managed and user managed transactions, it appears that the problem is that the transaction-type is specified as RESOURCE_LOCAL. In this case the following rules apply:

经过大量调查,包括尝试容器管理和用户管理的事务,问题似乎是事务类型被指定为 RESOURCE_LOCAL。在这种情况下,以下规则适用:

*  You must use the EntityManagerFactory to get an EntityManager
* The resulting EntityManager instance is a PersistenceContext/Cache
* An EntityManagerFactory can be injected via the @PersistenceUnit annotation only (not @PersistenceContext)
* You are not allowed to use @PersistenceContext to refer to a unit of type RESOURCE_LOCAL
* You must use the EntityTransaction API to begin/commit around every call to your EntityManger
* Calling entityManagerFactory.createEntityManager() twice results in two separate EntityManager instances and therefor two separate PersistenceContexts/Caches.
* It is almost never a good idea to have more than one instance of an EntityManager in use (don't create a second one unless you've destroyed the first)

In my case, I needed to use the manager factory to access the entitymanager, and use a persistenceUnit instead of a persistenceContext. The following code works just fine:

就我而言,我需要使用管理器工厂来访问实体管理器,并使用persistenceUnit 而不是persistenceContext。下面的代码工作得很好:

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)

public class RegisterUser implements RegisterUserLocal {

 @PersistenceUnit(unitName = "SCBCDEntities")
 private EntityManagerFactory factory;

 public void registerNewUser(String username, String password) {

  EntityManager entityManager = factory.createEntityManager();
  EntityTransaction entityTransaction = entityManager.getTransaction();
  entityTransaction.begin();

  User user = new User();
  user.setPassword(password);
  user.setUsername(username);

  entityManager.persist(user);
  entityTransaction.commit();
 }
}

Additional information about configuring transactions and the settings in the persistence.xml can be found here: http://openejb.apache.org/3.0/jpa-concepts.html

有关配置事务和persistence.xml 中设置的其他信息,请访问:http: //openejb.apache.org/3.0/jpa-concepts.html

回答by cletus

This might be because you haven't begun a transaction. Try:

这可能是因为您尚未开始交易。尝试:

public void registerNewUser(String username, String password){
  entityManager.getTransaction().begin();
  User user = new User();
  user.setPassword(password);
  user.setUsername(username);
  entityManager.persist(user);
  entityManager.getTransaction().commit();
}

Although I prefer not to do transaction handling this way. Instead I tend to use Spring's declarative transactions, which would look like this:

尽管我不喜欢以这种方式进行事务处理。相反,我倾向于使用 Spring 的声明性事务,它看起来像这样:

@Transactional
public void registerNewUser(String username, String password){
  User user = new User();
  user.setPassword(password);
  user.setUsername(username);
  entityManager.persist(user);
}

when configured.

配置时。

Edit:Another possibility is a problem I once had with EclipseLink where it wasn't writing everything to the database when I was running it in a J2SE environment (a console app to load some files into a database). In that case I had to explicitly flush()the EntityManagerto get all the records written.

编辑:另一种可能性是我曾经在使用 EclipseLink 时遇到的一个问题,当我在 J2SE 环境(一个将一些文件加载​​到数据库中的控制台应用程序)中运行它时,它没有将所有内容都写入数据库。在这种情况下,我必须明确flush()EntityManager让所有的记录写入。

回答by Gordon Yorke

You can not use the EntityTransaction (em.getTransaction()) because you are using a Container Managed Entity Manager (injected) so you must rely on the container for transactions. Have you set any transactional settings for the Stateless Session bean in XML? If you have not then it should work as the default should be 'Required'. You can try annotating 'registerNewUser' with @TransactionAttribute(TransactionAttributeType.REQUIRED)

您不能使用 EntityTransaction (em.getTransaction()),因为您使用的是容器管理的实体管理器(注入),因此您必须依赖容器进行事务。您是否为 XML 中的无状态会话 bean 设置了任何事务设置?如果您没有,那么它应该可以工作,因为默认值应该是“必需”。您可以尝试使用 @TransactionAttribute(TransactionAttributeType.REQUIRED) 注释“registerNewUser”

Alternatively you could create a user transaction before accessing the EM but a Container Managed transaction would be better.

或者,您可以在访问 EM 之前创建用户事务,但容器管理事务会更好。