以下のように、server_detail、server_group、server_group_mapping の 3 つのテーブルとエンティティ クラスがあります。(完全なコードの詳細は提供していません)
@Entity
@Table(name = "server_detail")
public class ServerBean implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "server_id")
private Integer ServerId;
@Column(name = "name")
private String serverName;
....
}
@Entity
@Table(name = "server_group")
public class ServerGroupBean implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "group_id")
private Integer groupId;
@Column(name = "name")
private String groupName;
....
}
@Entity
@IdClass(GroupMapPK.class)
@Table(name = "server_group_mapping")
public class ServerGroupMapBean implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "group_id")
private Integer groupId;
@Id
@Column(name = "server_id")
private Integer serverId;
....
}
以下のようにエンティティ Bean の操作を管理するために、各エンティティ Bean クラスには 1 つのラッパー クラスがあります。
@Stateless
@Local
public class ServerClient implements ServerLocal {
@PersistenceContext
private EntityManager em;
public ServerClient() {
}
public ServerBean create(java.lang.String name) {
ServerBean bean = new ServerBean(name);
em.persist(bean);
return bean;
}
public ServerBean update(ServerBean bean){
return (em.contains(bean) ? bean : em.merge(bean));
}
public void remove(ServerBean bean) {
em.remove(em.contains(bean) ? bean : em.merge(bean));
}
@Stateless
@Local
public class ServerGroupClient implements ServerGroupLocal {
@PersistenceContext
private EntityManager em;
public ServerGroupClient() {
}
public ServerGroupBean create(java.lang.Integer name) {
ServerGroupBean bean = new ServerGroupBean(name);
em.persist(bean);
return bean;
}
public ServerGroupBean update(ServerGroupBean bean){
return (em.contains(bean) ? bean : em.merge(bean));
}
public void remove(ServerGroupBean bean) {
em.remove(em.contains(bean) ? bean : em.merge(bean));
}
@Stateless
@Local
public class ServerGroupMapClient implements ServerGroupMapLocal {
@PersistenceContext
private EntityManager em;
public ServerGroupMapClient() {
}
public ServerGroupMapBean create(java.lang.Integer serverId,java.lang.Integer groupId ) {
ServerGroupMapBean bean = new ServerBean(serverId, groupId);
em.persist(bean);
return bean;
}
public ServerBean update(ServerBean bean){
return (em.contains(bean) ? bean : em.merge(bean));
}
public void remove(ServerBean bean) {
em.remove(em.contains(bean) ? bean : em.merge(bean));
}
テーブルとテーブル間の関係マッピングに MYSQL (innoDB Engine) を使用しています。
これで、server_group および server_group_mapping テーブル トランザクションを維持する GroupManager セッション Bean クラスができました。サーバーグループとメンバーを作成するたびに、次のトランザクションを実行する必要があります。
1. First, add group id and group name to server_group table
2. Second, map groupid with server id in server_group_mapping table
以下はコードです。
@Stateless
@Local
public class GroupManagerBean implements GroupManagerLocal {
@Resource
private SessionContext context;
private static GroupLocal GroupLocal;
private static GroupMapLocal GroupMapLocal;
public GroupManagerBean() {
GroupLocal = ServiceLocator.getGroupLocal();
smscMapLocal = ServiceLocator.getGroupMapLocal();
}
public void addGroup(GroupBean bean, Integer serverId){
group = GroupLocal.create(bean.getGroupName()); ---> 1
...
GroupMapLocal.create(group.getGroupId(), serverId); ----> 2
}
ServiceLocator クラスは、すべての Bean を検索できる場所です。デフォルトでは、ejb3 ではトランザクション属性が必要です。addGroup() メソッドを実行すると。次の例外が発生します。
javax.ejb.EJBTransactionRolledbackException: EntityManager must be access within a transaction
at org.jboss.ejb3.tx.Ejb3TxPolicy.handleInCallerTx(Ejb3TxPolicy.java:115)
at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:130)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:194)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptorv2.invoke(Ejb3AuthenticationInterceptorv2.java:186)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:41)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.BlockContainerShutdownInterceptor.invoke(BlockContainerShutdownInterceptor.java:67)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(CurrentInvocationInterceptor.java:67)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.ejb3.session.SessionSpecContainer.invoke(SessionSpecContainer.java:219)
at org.jboss.ejb3.proxy.handler.ProxyInvocationHandlerBase.invoke(ProxyInvocationHandlerBase.java:261)
....
Caused by: javax.persistence.TransactionRequiredException: EntityManager must be access within a transaction
at org.jboss.jpa.deployment.ManagedEntityManagerFactory.verifyInTx(ManagedEntityManagerFactory.java:155)
at org.jboss.jpa.tx.TransactionScopedEntityManager.persist(TransactionScopedEntityManager.java:186)
at com.example.GroupClient.create(GroupClient.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
エラー永続マネージャー (GroupClient および GroupMapClient) によると、トランザクションの範囲外です。知りたいのですが、永続マネージャーをトランザクションスコープに挿入しながら、トランザクションを完全に実行するにはどうすればよいですか?