eclipselink jpa、oracle、weblogic、calling persiveはデータベースにコミットしません
-
18-09-2019 - |
質問
私はちょうどJavaの持続性を見始めたばかりです(現在、EclipseのEclipselinkのデフォルトプロバイダーを使用して)。基本的に、オブジェクトを作成し、DB(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 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
@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;
}
}
また、この質問への返信に応答するために、ログをリストしたコードで、コミットが実行されていることを示しています(細心の詳細が削除されました)
[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
...
...
しかし、永続的に「フラッシュ」を追加すると、「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
...
...
解決
コンテナマネージドとユーザーマネージドトランザクションの両方を試すなど、多くの調査の後、問題はTransaction-Typeが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)
私の場合、Manager Factoryを使用してEntityManagerにアクセスし、PersistenceContextの代わりにPersistenceUnitを使用する必要がありました。次のコードは正常に機能します:
@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();
}
}
トランザクションの構成に関する追加情報とpersistence.xmlの設定については、こちらをご覧ください。 http://openejb.apache.org/3.0/jpaconcepts.html
他のヒント
コンテナマネージドエンティティマネージャー(注入)を使用しているため、EntityTransaction(em.getTransaction())を使用することはできません。 XMLのStateless Session Beanのトランザクション設定を設定しましたか?そうでない場合は、デフォルトが「必須」である必要があるため、機能する必要があります。 「RegisterNewuser」を@transactionAttribute(transactionAttributeType.required)で注釈することを試みることができます
または、EMにアクセスする前にユーザートランザクションを作成することもできますが、コンテナマネージドトランザクションの方が良いでしょう。
これは、あなたが取引を始めていないからかもしれません。試す:
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();
}
私はこの方法でトランザクション処理を行うことを好みませんが。代わりに、私はSpringの宣言的取引を使用する傾向がありますが、これは次のようになります。
@Transactional
public void registerNewUser(String username, String password){
User user = new User();
user.setPassword(password);
user.setUsername(username);
entityManager.persist(user);
}
構成したとき。
編集: 別の可能性は、J2SE環境(一部のファイルをデータベースにロードするコンソールアプリ)で実行しているときに、データベースにすべてを書き込んでいないEclipsElinkでかつて抱えていた問題です。その場合、私は明示的にしなければなりませんでした flush()
EntityManager
すべてのレコードを書くために。