2017-09-20 3 views
0

J'utilise Wildfly comme serveur Java EE. Nous avons un cadre que nous utilisons pour implémenter le type de modèle de conception de commande.Est-il possible de dire si une nouvelle transaction est démarrée dans JTA?

Je vais essayer de décrire le flux de travail aussi simple que possible:

  • Chaque commande est une entité qui stocke les informations sur la commande (horodatage de l'exécution, le statut de succès etc ..)
  • chaque commande a son CommandEJB dans lequel le BusinessLogic est exécuté
  • Toutes nos commandes sont Extented de la classe de commandement, et leurs EJBs sont prolongés de la classe CommandEJB
  • CommanEJB appelle la méthode d'exécution qui est remplacée pour la commande spécifique, où le busines s logique est exécutée pour cette commande spécifique
  • Après que le CommandEJB essaie de persister l'objet Command (qui porte l'information sur l'exécution de la commande comme décrit au point 1)
  • Si une implémentation de CommandEJB est en train de créer une entité et de la persister dans sa mise en œuvre de la méthode d'exécution, que nous faisons toujours une assotiation bidirectionnelle entre la commande spécifique et cette entité

Je vais essayer d'écrire quelques pseud-code pour expliquer comment cela fonctionne:

J'ai une entité appelée Personne et j'ai un CreatePersonCmd qui est la commande qui devrait créer une nouvelle personne et la conserver dans la base de données. Après cela, l'infrastructure conserve le CreatePersonCmd à la base de données. Lors de l'exécution de la commande, l'entité personne et l'entité CreatePersonCmd sont liés par

person.setCmd(cmd); et

cmd.setPerson(person); 

J'ai un service Web SAOP qui appelle la commande:

@Stateless 
@WebService 
public class MyWebService { 
CreatePersonCmd cmd = new CreatePersonCmd(); 
executor.execute(cmd); 
} 

Mon CreatePersonCmd est le propriétaire de la relation entre CreatePersonCommand et Person pour ressembler à ceci:

public class CreatePersonCmd { 
@JoinColumn 
@OneToOne 
private Person person; 
} 

De l'autre côté de la relation est Personne:

public class Person{ 
@OneToOne(mappedBy="person") 
private CreatePersonCmd createPersonCmd; 
} 

Dans mon CreatePersonEJB (dont la mise en œuvre méthode run est invoquée):

public class CreatePersonCmdEJB extends CommandEJB { 

public void run() { 

    Person person = new Person("John Doe"); 
    createPersonCmd.setPerson(person); 
    person.setCreatePersonCmd(createPersonCmd); 
    em.persist(person); 

} 

Après que le CommandEJB continue son exécution et tente de sauver la commande:

em.persist(createPersonCmd); 

Cependant, l'exécution n'arrive à cette dernière ligne, et je reçois une exception à:

em.persist(person); 

L'exception est:

Not-null property references a transient value - transient instance must be saved before current operation 

La chose étrange est que si je fais personne le propriétaire de la relation, tout fonctionne bien.

J'ai fait un exemple simple sans notre cadre qui a 2 entités Client et Adresse qui ont aussi une relation OneToOne bidirectionnelle et cependant je fais le test qu'il commet toujours bien, quel que soit l'ordre de persistance que j'utilise.

Voici le pseudo-code:

Customer c = new Customer("John Doe"); 
Address a = new Address("MyStreet", 1123); 

c.setAddress(a); 
a.setCustomer(c); 

em.persist(c); 
em.persist(a); 

Peu importe ce que l'ordre de persistait est (première adresse ou d'un client, il engage toujours très bien si j'ai deux lignes)

Cependant, dans notre cadre, il semble que les transactions se terminent après em.persist (personne), et je ne vois pas em.flush() dans notre code source.

Y at-il un moyen que je peux savoir si je suis dans la même transaction? J'ai essayé d'obtenir la transaction par em.getTransaction() mais je reçois A JTA EntityManager cannot use getTransaction(), probablement parce que les transatcions dans Java EE sont gérés par le conteneur d'application.

+0

'em.isJoinedToTransaction()' devrait vous dire si le 'em' est associée à une transaction active. – ujulu

Répondre

0

Si createPersonCmd est déjà inséré, vous devez l'ajouter à votre jeu de travail actuel. Cela peut être fait par

createPersonCmd = em.merge(createPersonCmd)