Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: [Résolu] Classe association (n-n) non représentée par un
PostPosted: Sat May 03, 2008 11:53 am 
Newbie

Joined: Thu May 01, 2008 6:18 am
Posts: 2
Bonjour,

Premier post sur ce forum, je vais essayer de ne pas faire de boulette.

Voilà mes mensurations :

- Java 1.5
- JoNAS 4.8.6
- Hibernate 3.2.0
- Base MySQL 5.05 avec le driver suivant : mysql-connector-java-5.0.4

Je fais mon mapping grâce à des annotations java.

Alors, je m'explique :

J'ai deux EJB entité, ProductBean (produit) et ProductStoreBean (magasin), tous deux représentés en base par des tables respectives :

Code:
TABLE [b]PRODUCT[/b] (
  IdProduct int(4),
  `Name` varchar(100),
  Description text ,
  PRIMARY KEY  (IdProduct)
)

TABLE [b]PRODUCT_STORE[/b] (
  IdProductStore int(4),
  `Name` varchar(100),
  Address varchar(100),
  PRIMARY KEY  (IdProductStore)
)



Dans le schéma UML de mon application, j'ai une classe association qui contient le prix du produit et le stock en magasin. Voici le schéma pour clarifier les choses :

Image

Elle est représentée en base comme ceci :

Code:
TABLE [b]P_PS[/b] (
  IdPS int(11),
  IdProduct int(11),
  Price double,
  Quantity int(11),
  PRIMARY KEY  (IdPS,IdProduct)
)


Cette classe d'association n'est pas représentée par un EJB (c'est volontaire) et je pense que c'est là d'où vient le problème.


Voici le code Java de mes deux EJB, avec les annotations :

Code:
@Entity
@Table(name = "PRODUCT")

/* Native Query
* Let Hibernate take care mapping from JDBC result sets to business objects
*/
@SqlResultSetMapping(name="getProduct", entities =
        @EntityResult(entityClass=ecom.beans.ProductBean.class, fields= {
           @FieldResult(name="idproduct", column="idproduct"),
           @FieldResult(name="name", column="name"),
            @FieldResult(name="description", column="description")
        })
)
public class ProductBean implements java.io.Serializable {

   private static final long serialVersionUID = -8268676536403879578L;

   /**
    * Primary Key (automatically generated)
    */
   @Id
   @Column(name="IdProduct")
   private long idProduct;

   private String name;

   private String description;
   

   //C'est ici que je fais la jointure vers ma table P_PS
   
   @ManyToMany
   @JoinTable(name="P_PS",
   joinColumns=
      @JoinColumn(name="IdProduct", referencedColumnName="IdProduct"),
   inverseJoinColumns=
      @JoinColumn(name="IdPS", referencedColumnName="IdProductStore")
   )
   protected Set<ProductStoreBean> stores;

   
   public ProductBean() {
   }

   public ProductBean(String nameProduct, String desc) {
      this.name = nameProduct;
      this.description = desc;
   }
   
   /**
    * Getter and setter for the idProduct attribute
     * Mapping persistent attribute IDPRODUCT in SQL table Product
    * @return idProduct
    */
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "IDPRODUCT", nullable = false)
   public long getIdProduct() {
      return this.idProduct;
   }
   public void setIdProduct(long id) {
      this.idProduct = id;
   }

   /**
    * Getter and setter for the name attribute
     * Mapping persistent attribute NAME in SQL table Product
    * @return name
    */
   @Column(name = "NAME", nullable = false)
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }

   /**
    * Getter and setter for the description attribute
     * Mapping persistent attribute DESCRIPTION in SQL table Product
    * @return description
    */
   @Column(name = "DESCRIPTION", nullable = false)
   public String getDescription() {
      return this.description;
   }
   public void setDescription(String desc) {
      this.description = desc;
   }
}

-----------------------------------------

@Entity
@Table(name = "PRODUCT_STORE")

/* Native Query
* Let Hibernate take care mapping from JDBC result sets to business objects
*/
@SqlResultSetMapping(name="getProductStore", entities =
        @EntityResult(entityClass=ecom.beans.ProductStoreBean.class, fields= {
           @FieldResult(name="idProductStore", column="idProductStore"),
           @FieldResult(name="name", column="name"),
            @FieldResult(name="address", column="address"),
            @FieldResult(name="IdAccount", column="IdAccount")
        })
)
public class ProductStoreBean implements java.io.Serializable{

   private static final long serialVersionUID = 901708405403817644L;

   private long idProductStore;
   
        //Mapping de la jointure
        /**
    * Products stored
    */
   @ManyToMany (cascade = CascadeType.REMOVE, mappedBy = "stores")
   protected Set<ProductBean> products;


   private String name;

   private String address;

   
    public ProductStoreBean(){};

    public ProductStoreBean (String name, String address, AccountBean account)
    {
       this.name = name;
       this.address = address;
       this.account = account;       
    }
       
    /**
    * Getter and setter for the idProductStore attribute
     * Mapping persistent attribute IDPRODUCTSTORE in SQL table Product_Store
    * @return idProductStore
    */
    @Id
    @GeneratedValue (strategy=GenerationType.AUTO)
    @Column(name="IDPRODUCTSTORE", nullable = false)
    public long getIdProductStore(){
        return this.idProductStore;
    }
    public void setIdProductStore(long id){
        this.idProductStore = id;
    }
   
    /**
    * Getter and setter for the name attribute
     * Mapping persistent attribute NAME in SQL table Product_Store
    * @return name of the product store
    */
    @Column(name="NAME", nullable = false)
    public String getName(){
        return name;
    }
    public void setName(String n){
        this.name=n;
    }

   /**
    * Getter and setter for the address attribute
     * Mapping persistent attribute ADDRESS in SQL table Product_Store
    * @return address
    */
    @Column(name="ADDRESS", nullable = false)
    public String getAddress(){
        return address;
    }
    public void setAddress(String n){
        this.address=n;
    }
   
    /**
    * Getter and setter for the account attribute
     * Mapping relationship with idAccount field in table ACCOUNT
    * @return account
    */
    @OneToOne (cascade = CascadeType.REMOVE)
    @JoinColumn(name="IDACCOUNT", referencedColumnName="IdAccount")
    public AccountBean getAccount() {
      return this.account;
   }
   public void setAccount(AccountBean idAccount) {
      this.account = idAccount;
   }
}



J'ai d'abord une question : peut-on accéder avec Hibernate à cette table qui n'a pas d'EJB correspondant, comme je le fais avec les deux autres EJB ? Mon prof java me dit que oui, mais pas JoNAS !
Il me dit que ma table d'association n'est pas mappée.

L'ajout/la modification/la suppression en base fonctionnent parfaitement pour mes deux EJB Product et ProductStore, mais j'ai un problème pour manipuler les données de la table association P_PS.

Je le fais à partir d'un autre Bean d'administration, grâce à un EntityManager.

Les SELECT fonctionnent très bien, par exemple :

Code:
Query q = entityManager.createNativeQuery("SELECT * FROM product WHERE IdProduct IN (SELECT IdProduct FROM P_PS WHERE IdPS ="+ idStore +")", ProductBean.class);
return q.getResultList();



Mais lorsque je veux modifier les données de cette table, c'est là qu'arrivent les problèmes. Par exemple, pour supprimer une ligne de cette table d'association, mon code est le suivant :

Code:
entityManager.createQuery("DELETE FROM P_PS WHERE IdPS ="+ store +" AND IdProduct ="+id);


Voici ce que JoNAS me répond :

Quote:
2008-05-03 17:39:18,109 : AbsTransactionInterceptor.handleContextContainerTransa
ction : Exception (not application exception) in business method
java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException:
P_PS is not mapped
[DELETE FROM P_PS WHERE IdPS =1 AND IdProduct =1]
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException
(AbstractEntityManagerImpl.java:634)
at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntit
yManagerImpl.java:95)
at org.objectweb.easybeans.persistence.TxEntityManager.createQuery(TxEnt
ityManager.java:224)
at ecom.beans.EcomAdminBean.original$EasyBeans$deleteProductInStore(Ecom
AdminBean.java:266)
at org.objectweb.easybeans_gen.invocationcontext.ecom.beans.EcomAdminBea
n.EasyBeansInvocationContextImpldeleteProductInStoreAROUNDINVOKE39217845.proceed
(Unknown Source)
at org.objectweb.easybeans.transaction.interceptors.CMTRequiredTransacti
onInterceptor.intercept(CMTRequiredTransactionInterceptor.java:110)
at org.objectweb.easybeans_gen.invocationcontext.ecom.beans.EcomAdminBea
n.EasyBeansInvocationContextImpldeleteProductInStoreAROUNDINVOKE39217845.proceed
(Unknown Source)
at org.objectweb.easybeans.naming.interceptors.JOnASENCInterceptor.inter
cept(JOnASENCInterceptor.java:147)
at org.objectweb.easybeans_gen.invocationcontext.ecom.beans.EcomAdminBea
n.EasyBeansInvocationContextImpldeleteProductInStoreAROUNDINVOKE39217845.proceed
(Unknown Source)
at ecom.beans.EcomAdminBean.deleteProductInStore(EcomAdminBean.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.objectweb.easybeans.container.session.stateful.StatefulSessionFac
tory.localCall(StatefulSessionFactory.java:201)
at org.objectweb.easybeans.container.session.SessionFactory.rpcInvoke(Se
ssionFactory.java:178)
at org.objectweb.easybeans.rpc.rmi.server.RMIServerRPCImpl.getEJBRespons
e(RMIServerRPCImpl.java:105)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294)
at org.objectweb.carol.rmi.jrmp.server.JUnicastServerRef.dispatch(JUnica
stServerRef.java:143)
at sun.rmi.transport.Transport$1.run(Transport.java:153)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:4
66)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport
.java:707)
at java.lang.Thread.run(Thread.java:595)


Comment faire pour manipuler les données de cette table avec Hibernate ? Dois-je obligatoirement la représenter par un Entity Bean ?
Dois-je faire un autre ResultSetMapping ? Si oui, dans quelle classe ?
Suis-je en train de complètement me fourvoyer et dois-je arrêter le java ?

Je reste aux aguets, merci de votre aide ;)


Last edited by camouille on Wed May 14, 2008 4:50 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed May 14, 2008 4:44 am 
Newbie

Joined: Thu May 01, 2008 6:18 am
Posts: 2
Je me réponds tout seul :

J'ai finalement mappé mon association et créé un EJB entité.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.