Hi,
I'm trying to use hibernate to map a many-to-many relation with some attributes in the shared table. Then I can't use the many-to-many relation, so i decided to use many-to-one and one-to-many relations with some attributes in the shared table.
The database is composed by tree tables, the first table called productes contains products ids and descriptions, the second table called clients contains the name and identifier of the clients and the last table create the M-N realtion between the clients and articles, this table is called CLIENTS_has_PRODUCTES.
the following code creates de database:
CREATE TABLE PRODUCTES (
ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
DESCRIPCIO Varchar(45) NULL,
PRIMARY KEY(ID)
);
CREATE TABLE CLIENTS (
ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
NOM Varchar(45) NULL,
PRIMARY KEY(ID)
);
CREATE TABLE CLIENTS_has_PRODUCTES (
CLIENTS_ID INTEGER UNSIGNED,
PRODUCTES_ID INTEGER UNSIGNED,
DATA Varchar(45) NULL,
PRIMARY KEY(CLIENTS_ID,PRODUCTES_ID),
FOREIGN KEY(CLIENTS_ID)
REFERENCES CLIENTS(ID),
FOREIGN KEY(PRODUCTES_ID)
REFERENCES PRODUCTES(ID)
);
the classes I use to map this database in java are:
public class ClientBean {
private int id=0;
private String nom;
private Set sells; //Objects Type hibernate_beans.Sells
//getters and setter
}
public class ArticleBean {
private int id=0;
private String descripcio;
private Set sells; //Objects Type hibernate_beans.Sells
private Sells s;
//getters and setters
}
the third class implements the shared table:
public class Sells{
private SellsID id;
private String data = null;
//getters and setters
}
as you can see this class contains another class as an ID, which is:
public class SellsID implements Serializable {
private ArticleBean itemId;
private ClientBean clientId;
public SellsID() {
this.itemId = null;
this.clientId = null;
}
public boolean equals(Object o) {
if (o instanceof SellsID) {
SellsID that = (SellsID)o;
return that.itemId == this.itemId && that.clientId == this.clientId;
} else {
return false;
}
}
public int hashCode() {
return itemId.hashCode() + clientId.hashCode();
}
//getters and setters
}
for mapping all this classes to hibernate I use the following mapping file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-lazy="false">
<!--ClientBean-->
<class name="hibernate_beans.ClientBean" table="CLIENTS">
<id name="id" type="int" column="ID" unsaved-value="0">
<generator class="native"/>
</id>
<property name="nom" type="string" column="NOM"/>
<set name="sells" cascade="all" inverse="false" lazy="false">
<key column="CLIENTS_ID"/>
<one-to-many class="hibernate_beans.Sells"/>
</set>
</class>
<!--ArticleBean-->
<class name="hibernate_beans.ArticleBean" table="PRODUCTES">
<id name="id" type="int" column="ID" unsaved-value="0">
<generator class="native"/>
</id>
<property name="descripcio" type="string" column="DESCRIPCIO"/>
<set name="sells" cascade="all" inverse="false" lazy="false">
<key column="PRODUCTES_ID"/>
<one-to-many class="hibernate_beans.Sells"/>
</set>
</class>
<!--ClientBean-->
<class name="hibernate_beans.Sells" table="CLIENTS_has_PRODUCTES">
<composite-id class="hibernate_beans.SellsID" access="field" unsaved-value="any" >
<key-many-to-one name="itemId" class="hibernate_beans.ArticleBean" column="PRODUCTES_ID"/>
<key-many-to-one name="clientId" class="hibernate_beans.ClientBean" column="CLIENTS_ID"/>
</composite-id>
<property name="data" type="string" column="DATA"/>
</class>
</hibernate-mapping>
I have checked some examples from internet and also the hibernate project caveatemptor-0.9.5, which does something similar to what i'm trying to do.
I don't know if this code is correct, or if i understood something wrong form the web tutorial, but it does not do what i want.
When i try to execute the following lines to insert and element:
Session session = HibernateHelper.getSessionFactory().getCurrentSession();
session.beginTransaction();
ClientBean client = new ClientBean();
client.setNom("Albert");
session.saveOrUpdate(client);
ArticleBean article = new ArticleBean();
article.setDescripcio("cargols pel cap");
session.saveOrUpdate(article);
client.setSells(new HashSet());
article.setSells(new HashSet());
Sells sells = new Sells();
//sells.setClient(client);
//sells.setArticle(article);
sells.setData("data");
article.getSells().add(sells);
client.getSells().add(sells);
session.getTransaction().commit();
i get the following error:
Hibernate: insert into CLIENTS (NOM) values (?)
Hibernate: insert into PRODUCTES (DESCRIPCIO) values (?)
Exception in thread "main" org.hibernate.HibernateException: The class has no identifier property: hibernate_beans.Sells
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:174)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:3596)
at org.hibernate.id.Assigned.generate(Assigned.java:28)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:99)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:131)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:122)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:65)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at hibernate_beans.provaHibernate.main(provaHibernate.java:44)
I exactlly don't understat what is happening here, i see that the client is correctly introduced to the database but not the product, about the exceptions java throws i do not understant exactly what it means, looks like if hibernate was trying to find a Sells class in Productes class???
Can anyone check if the mapping is correct?
I would appreciate any help or comment about what should and should't do?
I will also appreciate if anyone can show me where I can find a complet example of how to implement a many-to-many relation using many-to-one and one-to-many realtions.
Thanks in advance.
albert.sole
|