Hibernate Entity manager de chasse d'eau automatique avant de requête et de valider les modifications apportées à la DB dans la transaction
Je suis de l'utilisation d'Hibernate 3.6.0 avec JPA 2 sur Jboss as 6.0.0 final.
Dans un EJB de la mine, il y a une méthode de mise à jour de l'entité de valeurs, et faire de la requête. Toute la méthode est en cours d'exécution dans une GSM transaction. Si quelque chose tombe en panne, toutes les modifications doivent être de restauration et nous engageons à ne pas DB.
La Base de données est mySql.
Avant d'exécuter JPA requête, JPA sera chasse d'eau automatique le changement des états de DB, afin d'éviter toutes les données obsolètes de revenir. Toutefois, au sein de ma méthode, l'auto-flush directement la mise à jour et valide les modifications dans la base de données et même quelque chose a mal tourné par la suite, les modifications ne sont pas de restauration. Donc je voudrais vous demander si il y a mauvaise configuration de mon set up ou c'est un bug ou quelque chose.
EJB
@Stateless(mappedName = "MyManagementBean")
@Local
@TransactionManagement(TransactionManagementType.BEAN)
public class MyManagement implements MyManagementLocal,MyManagementRemote {
@PersistenceUnit(unitName="MyEjb") EntityManagerFactory emf;
@Resource UserTransaction utx;
@Resource SessionContext ctx;
/**
* Default constructor.
*/
public MyManagement () {
//TODO Auto-generated constructor stub
}
public void dosomething(String id) throws Exception
{
try {
utx.begin();
em = emf.createEntityManager();
Myline line = em.find(Myline.class, id);
line.setStatus("R");
Stromg q += " from Myline as line ";
//auto flush apply here and directly committed to DB...
Iterator iter = em.createQuery(q).getResultList().iterator();
em.flush();
utx.commit();//changes should only commit after this
}
catch (Exception e) {
e.printStackTrace();
if (utx != null) utx.rollback();
throw e; //or display error message
}
finally {
em.close();
}
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="MyEjb" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:MyDS</jta-data-source>
<class>com.quincy.entity.MyLine</class>
<properties>
<property name="hibernate.connection.defaultNChar" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLMyISAMDialect"/>
<property name="hibernate.ejb.cfgfile" value="META-INF/hibernate.cfg.xml"/>
</properties>
</persistence-unit>
</persistence>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<property name="hibernate.max_fetch_depth">3</property>
</session-factory>
</hibernate-configuration>
mysql-ds.xml
<datasources>
<local-tx-datasource>
<jndi-name>MyDS</jndi-name>
<connection-url>jdbc:mysql://10.10.150.57:3306/myds</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>user</user-name>
<password>pwd</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
Après enquête, j'ai découvert que quand il y a une chasse d'eau, la sale les modifications sont écrites et engagée dans la base de données directement. Si je supprime le flush(), tout fonctionne bien. Cependant, le système est déclenché rincer avant de requête et je pense que c'est nécessaire.
Il me semble que la db est automatiquement engagé. J'ai essayé de définir la propriété hibernate.connection.autocommit
à false
mais le problème persiste et un EJB avertissement de violation de la spec est invité.
Mise à JOUR: La cause doit venir de mysql. Comme si je change de serveur mssql, le problème disparaît.J'ai aussi essayé de mysql avec xa-datasource
, toujours pas de chance...
P: Merci pour la réponse. J'ai mis à jour pour inclure le jdbc. Mysql version 5.0 et je suis en utilisant mysql-connector-java-5.1.13
OriginalL'auteur Quincy | 2011-06-29
Vous devez vous connecter pour publier un commentaire.
Problème résolu.
La cause est que les tables dans la base de données mysql est à l'aide de
MyISAM
moteur par défaut et les tableaux à l'aide de ce moteur ne prennent pas en charge de la transaction.Commutation des tables de
innoDB
rendre la chose fonctionne.Espérons que cela serait utile pour toute personne, de sorte qu'ils ne seront pas perdre autant de temps que je l'ai fait. 🙁
OriginalL'auteur Quincy
Ce qui est défini comme l'entityManager FlushModeType
La méthode prend un enum défini ici.
Aussi essayer de vérifier les éléments suivants
après la déclaration de l'Entité gestionnaire de l'usine.
Si j'ai mis la couleur mode de COMMETTRE, de la chasse d'eau ne risque pas d'arriver. Cependant, la requête retourne des données périmées. Le problème est maintenant de la chasse d'eau est en train de commettre les changements dans la base de données directement. Il est censé ne chasse que les modifications DB mais ne pas commettre.
Ne pouvez-vous pas l'exécution de la requête (avec des données synchronisées) d'abord, puis changer pour la ligne et ensuite engager?
Pas de. Pendant le processus de requête, il y a une sorte de vérification et peut entraîner une défaillance. Je veux que les modifications de la fonction restauration dans ce cas. Dans ma compréhension, même flush mode est réglé sur AUTO, les changements ne seraient vidées pour être visible pour les autres requêtes, mais pas directement engagés dans la bd. Donc je me demandais si j'avais fait quelque chose de mal avec ma config. (C'est ma première fois l'utilisation de l'API JPA, j'ai été en utilisant natif hibernate avant)
Après enquête, j'ai découvert que quand il y a une chasse d'eau, la sale les modifications sont écrites et engagée dans la base de données directement. Il semble que l'em n'est pas vraiment contraignant à une transaction. Cependant, je ne peux toujours pas travailler. :/
OriginalL'auteur Luke