IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JPA Java Discussion :

JPA/Hibernate /@TransactionManagement => pas de transactions


Sujet :

JPA Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut JPA/Hibernate /@TransactionManagement => pas de transactions
    Bonjour,
    Je n'arrive pas à mettre en place les transactions dans un environnement JPA/Hibernate et annotations.
    Voici le contexte :
    J'ai choisi l'option TABLE pour générer la clé primaire de la table employee, cette clé primaire est bien générée, mais comme sa génération n'est pas prise dans la même transaction que celle de la création de la nouvelle occurrence de employee, j'ai une erreur duplicate primary key. Voici les détails de mon environnement de travail (il s'agit d'une reproduction sur un petit exemple et pas de l'application réelle, mais ce sera plus simple à comprendre) :
    IDE : NetBeans 11.2
    Type d'application : Enterprise Application nommée EmployeesJPA (ant) avec deux modules : EmployeesJPA-ejb et EmployeesJPA-war
    ORM : JPA avec implémentation sous Hibernate 4.3
    Base de données : MySql
    EJB Entity : Employee
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    @Entity
    @Table(name = "employee")
    @XmlRootElement
    @NamedQueries({
        @NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e"),
        @NamedQuery(name = "Employee.findByEmployeeId", query = "SELECT e FROM Employee e WHERE e.employeeId = :employeeId"),
        @NamedQuery(name = "Employee.findByName", query = "SELECT e FROM Employee e WHERE e.name = :name"),
        @NamedQuery(name = "Employee.findByManagerId", query = "SELECT e FROM Employee e WHERE e.managerId = :managerId"),
        @NamedQuery(name = "Employee.findByHiredate", query = "SELECT e FROM Employee e WHERE e.hiredate = :hiredate"),
        @NamedQuery(name = "Employee.findBySalary", query = "SELECT e FROM Employee e WHERE e.salary = :salary")})
    public class Employee implements Serializable {
     
        private static final long serialVersionUID = 1L;
        @Id
        @TableGenerator(name="EmployeePk", table="pkeys", pkColumnName="pkey_id",
                valueColumnName="pkey_val", pkColumnValue="EMPLOYEE", allocationSize=1)
        @GeneratedValue(strategy=GenerationType.TABLE, generator="EmployeePk")    
        @Basic(optional = false)
        @NotNull
        @Column(name = "employee_id")
        private Integer employeeId;
        . . .
    EJB Session EmployeeFacade
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    @Stateless
    @LocalBean
    @TransactionManagement(TransactionManagementType.CONTAINER)
    public class EmployeeFacade {
        @PersistenceContext(unitName = "EmployeesJPA-ejbPU")
        private EntityManager em;
        @EJB
        JobFacade jobFacade;
        @EJB
        DepartmentFacade departmentFacade;
     
        @TransactionAttribute(TransactionAttributeType.REQUIRED)
        public void addEmployee(String name, Date hiredate, double salary, int jobId, int departmentId, int managerId) throws Exception {
            Employee employee = new Employee();
            try{
                Department department = departmentFacade.getDepartmentById(departmentId);
                Job job = jobFacade.getJobById(jobId);
                employee.setDepartment(department);
                employee.setJob(job);
                employee.setHiredate(hiredate);
                employee.setManagerId(managerId);
                employee.setName(name);
                em.persist(employee);
            }catch(Exception ex){
                throw ex;
            }
        }
    }
    Servlet SrvlEmployee
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
        protected void processRequest(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String error = null;
            try {
                Date hiredate = Utilitaire.StrToDate("2020-02-01", "yyyy-MM-dd");
                BigDecimal salary = new BigDecimal(2000.00);
                employeeFacade.addEmployee("Smith", hiredate, salary, 2, 3, 4);
            } catch (Exception e) {
                error = Utilitaire.getExceptionCause(e);
            } finally {
                request.setAttribute("errorR", error);
                RequestDispatcher dsp = request.getRequestDispatcher("/index.jsp");
                dsp.forward(request, response);
            }
        }
    Table pkeys avant insertion :
    Nom : pkeyBefore.PNG
Affichages : 300
Taille : 7,2 Ko
    Table pkeys après insertion :
    Nom : pkeyAfter.PNG
Affichages : 245
Taille : 6,1 Ko
    L'id de la dernière occurrence de employee est 14.
    La trace des requêtes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Hibernate: select department0_.department_id as departme1_0_0_, department0_.dname as dname2_0_0_, department0_.location as location3_0_0_ from department department0_ where department0_.department_id=?
    Hibernate: select job0_.job_id as job_id1_2_0_, job0_.jobname as jobname2_2_0_ from job job0_ where job0_.job_id=?
    Hibernate: select pkey_val from pkeys where pkey_id = 'EMPLOYEE' for update
    Hibernate: update pkeys set pkey_val = ? where pkey_val = ? and pkey_id = 'EMPLOYEE'
    Hibernate: insert into employee (department_id, hiredate, job_id, manager_id, name, salary, employee_id) values (?, ?, ?, ?, ?, ?, ?)
    Le message d'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SQL Error: 1062, SQLState: 23000
    Duplicate entry '14' for key 'PRIMARY'
    Précisions :
    - le même code sous EclipseLink fonctionne parfaitement !
    - j'ai essayé le REQUIRES_NEW à la place de REQUIRED, cela n'a rien changé.
    Voilà, si quelqu'un a une idée, je serais bien preneur !
    Merci d'avance pour votre aide.

  2. #2
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    D'après ce que j'ai lu sur le net, il semblerait qu'en mettant une valeur autre que 1 dans allocationSize corrige le problème...

    Mais bon, tu devrais utiliser un auto incrément géré par MySQL, beaucoup moins lourd.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    D'après ce que j'ai lu sur le net, il semblerait qu'en mettant une valeur autre que 1 dans allocationSize corrige le problème...

    Mais bon, tu devrais utiliser un auto incrément géré par MySQL, beaucoup moins lourd.
    Bonjour,
    Merci pour cette réponse, je vais tester. Pour ce qui concerne l'auto-incrémentation, j'ai effectivement fini par opter pour cette solution, mais elle n'est pas totalement satisfaisante.
    Est-ce qu'éventuellement tu aurais conservé les liens vers cette solution ?
    Je teste ta solution et reviens pour dire ce qu'il en est.
    A bientôt.

  4. #4
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    La discussion que j'avais trouvé est ici.
    Et un autre article qui traite du sujet ici.

    Tu disais que la solution ne te convenais pas trop... J'imagine que tu aimerais avoir des numéros consécutifs ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 179
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Bonjour,

    La discussion que j'avais trouvé est ici.
    Et un autre article qui traite du sujet ici.

    Tu disais que la solution ne te convenais pas trop... J'imagine que tu aimerais avoir des numéros consécutifs ?
    Bonjour
    J'ai testé avec allocationSize=2, c'est du grand n'importe quoi, à la première insertion employee_id prend la valeur 28 (la dernière était 14 !), puis 29, 30, 31 ... pendant ce temps keys_id passe à 15, puis ne bouge pas puis 16, puis ne bouge pas ...
    J'y perds mon latin ;-)
    Je me demande si ce n'est pas l'implémentation JPA d'Hibernate qui est en cause parce que cela fonctionne parfaitement sous EclipsLink !
    La raison pour laquelle je voudrais utiliser l'option TABLE, c'est que j'aurais besoin de la clé générée pour enchaîner les insertions dans le cadre d'une seule transaction, exemple : Commande(commande_id), LigneCde (commande_id, article_id), Article(maj qtestock) ...
    Est-ce qu'éventuellement je peux te donner un lien vers mon exemple pour que tu puisses le tester ?

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par clem_alain Voir le message
    Est-ce qu'éventuellement je peux te donner un lien vers mon exemple pour que tu puisses le tester ?
    Oui, aucun problème, d'autant que j'utilise Hibernate sur mon serveur, je pourrai plus facilement voir ce qui se passe.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. Pourquoi Hibernate et non pas JPA
    Par clubist dans le forum Hibernate
    Réponses: 5
    Dernier message: 15/12/2010, 14h58
  2. Réponses: 0
    Dernier message: 25/08/2009, 15h32
  3. [JPA / Hibernate] Cascade qui ne cascade pas !
    Par dazz_x dans le forum Persistance des données
    Réponses: 1
    Dernier message: 11/09/2007, 13h35
  4. Réponses: 3
    Dernier message: 01/06/2006, 16h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo