Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
Hibernate version:3.13
Mapping documents + POJOS + Database tables :
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<class
name="com.company.dreams.domainmodel.Advert"
table="ADVERT"
>
<id
name="id"
type="java.lang.Integer"
column="ID"
>
<generator class="native" />
</id>
<property
name="reference"
type="java.lang.String"
column="REFERENCE"
length="20"
>
</property>
<!-- Associations -->
<!-- bi-directional one-to-many association to Transaction -->
<set
name="transactions"
lazy="true"
cascade="all"
>
<key>
<column name="ADVERT_ID" />
</key>
<one-to-many
class="com.company.dreams.domainmodel.Transaction"
/>
</set>
</class>
</hibernate-mapping>
<?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>
<class
name="com.company.dreams.domainmodel.Transaction"
table="TRANSACTION"
>
<composite-id name="comp_id" class="com.company.dreams.domainmodel.TransactionPK">
<key-property
name="usersId"
column="USERS_ID"
type="java.lang.Integer"
length="10"
>
</key-property>
<key-property
name="advertId"
column="ADVERT_ID"
type="java.lang.Integer"
length="10"
>
</key-property>
<key-property
name="startDate"
column="START_DATE"
type="java.sql.Timestamp"
length="19"
>
</key-property>
</composite-id>
<property
name="amount"
type="java.lang.Float"
column="AMOUNT"
length="12"
>
</property>
<!-- Associations -->
<many-to-one
name="advert"
class="com.company.dreams.domainmodel.Advert"
update="false"
insert="false"
>
<column name="ADVERT_ID" />
</many-to-one>
<many-to-one
name="users"
class="com.company.dreams.domainmodel.Users"
update="false"
insert="false"
>
<column name="USERS_ID" />
</many-to-one>
</class>
</hibernate-mapping>
<?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>
<joined-subclass
extends="com.company.dreams.domainmodel.Advert"
name="com.company.dreams.domainmodel.Housing" table="HOUSING">
<key column="advert_id" foreign-key="housing_references_advert"/>
</joined-subclass>
</hibernate-mapping>
package com.company.dreams.domainmodel;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;
/**
* @hibernate.class
* table="ADVERT"
*
*/
public abstract class Advert implements Serializable {
/** identifier field */
private Integer id;
/** persistent field */
private Set transactions;
/** default constructor */
public Advert() {
}
/**
* Retrouve le propriétaire de l'annonce grâce à ses transactions
*
* @return
*/
public Users getOwner() {
Users owner = null;
if (getTransactions() != null && getTransactions().size() > 0)
owner = ((Transaction)getTransactions().iterator().next()).getUsers();
return owner;
}
/**
* @hibernate.id
* generator-class="native"
* type="java.lang.Integer"
* column="ID"
*
*/
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
/**
* @hibernate.property
* column="REFERENCE"
* length="20"
*
*/
public String getReference() {
return this.reference;
}
public void setReference(String reference) {
this.reference = reference;
}
/**
* @hibernate.set
* lazy="true"
* inverse="true"
* cascade="all"
* @hibernate.collection-key
* column="ADVERT_ID"
* @hibernate.collection-one-to-many
* class="com.company.dreams.domainmodel.Transaction"
*
*/
public Set getTransactions() {
return this.transactions;
}
public void setTransactions(Set transactions) {
this.transactions = transactions;
}
public Transaction getCurrentTransaction() {
if (transactions == null || transactions.size() == 0) return null;
List l = new ArrayList(transactions);
if (l.size() == 1) return (Transaction)l.get(0);
Transaction t = null;
Date now = new Date();
Collections.sort(l, new Comparator() {
public int compare(Object o1, Object o2) {
Transaction t1 = (Transaction)o1;
Transaction t2 = (Transaction)o2;
return t2.getPublishDate().compareTo(t1.getPublishDate());
}
});
Iterator it = l.iterator();
while (it.hasNext()) {
if (t.getPublishDate()!= null
&& now.compareTo(t.getPublishDate()) > 0
&& t.getEndDate() != null
&& now.compareTo(t.getEndDate()) < 0) return t;
}
return t;
}
}
package com.company.dreams.domainmodel;
import java.io.Serializable;
import java.util.Date;
import java.util.Set;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
/**
* @hibernate.class
* table="TRANSACTION"
*
*/
public class Transaction implements Serializable {
public static final int PAYMENT_STATUS_UNKNOWN = 0;
public static final int PAYMENT_STATUS_AWAITING = 1;
public static final int PAYMENT_STATUS_COMPLETE = 2;
public static final int PAYMENT_STATUS_REFUSED = 3;
/** identifier field */
private com.company.dreams.domainmodel.TransactionPK comp_id;
/**
* Montant de la transaction
*/
private Float amount;
/** nullable persistent field */
private com.company.dreams.domainmodel.Advert advert;
/** nullable persistent field */
private com.company.dreams.domainmodel.Users users;
/** default constructor */
public Transaction() {
}
/**
* @return the complete
*/
public boolean isFinished() {
return (this.finishDate != null
&& this.comp_id.getStartDate() != null
&& this.finishDate.compareTo(this.comp_id.getStartDate()) > 0);
}
/**
* Etat de paiement de la transaction<br>
* - payée
* - en attente
* - refusée
*/
public int getPaymentStatus() {
int status = PAYMENT_STATUS_UNKNOWN;
if (!isFinished() || !isPaid()) status = PAYMENT_STATUS_AWAITING;
if (isFinished() && !isPaid()) status = PAYMENT_STATUS_REFUSED;
if (isFinished() && isPaid()) status = PAYMENT_STATUS_COMPLETE;
return status;
}
/**
* @hibernate.id
* generator-class="assigned"
*
*/
public com.company.dreams.domainmodel.TransactionPK getComp_id() {
return this.comp_id;
}
public void setComp_id(com.company.dreams.domainmodel.TransactionPK comp_id) {
this.comp_id = comp_id;
}
/**
* @hibernate.property
* column="AMOUNT"
* length="12"
*
*/
public Float getAmount() {
return this.amount;
}
public void setAmount(Float amount) {
this.amount = amount;
}
/**
* @hibernate.many-to-one
* update="false"
* insert="false"
*
* @hibernate.column
* name="ADVERT_ID"
*
*/
public com.company.dreams.domainmodel.Advert getAdvert() {
return this.advert;
}
public void setAdvert(com.company.dreams.domainmodel.Advert advert) {
this.advert = advert;
}
/**
* @hibernate.many-to-one
* update="false"
* insert="false"
*
* @hibernate.column
* name="USERS_ID"
*
*/
public com.company.dreams.domainmodel.Users getUsers() {
return this.users;
}
public void setUsers(com.company.dreams.domainmodel.Users users) {
this.users = users;
}
public String toString() {
return new ToStringBuilder(this)
.append("comp_id", getComp_id())
.toString();
}
public boolean equals(Object other) {
if ( (this == other ) ) return true;
if ( !(other instanceof Transaction) ) return false;
Transaction castOther = (Transaction) other;
return new EqualsBuilder()
.append(this.getComp_id(), castOther.getComp_id())
.isEquals();
}
public int hashCode() {
return new HashCodeBuilder()
.append(getComp_id())
.toHashCode();
}
}
package com.company.dreams.domainmodel;
/**
* @hibernate.class
* table="HOUSING"
*
*/
public class Housing extends Advert {
/** identifier field */
//private Integer advertId;
// /**
// * @hibernate.id
// * generator-class="native"
// * type="java.lang.Integer"
// * column="ADVERT_ID"
// *
// */
// public Integer getAdvertId() {
// return this.advertId;
// }
//
// public void setAdvertId(Integer advertId) {
// this.advertId = advertId;
// }
}
CREATE TABLE ADVERT (
ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
REFERENCE VARCHAR(20) NOT NULL,
PRIMARY KEY(ID)
)
TYPE=InnoDB;
CREATE TABLE TRANSACTION (
USERS_ID INTEGER UNSIGNED NOT NULL,
ADVERT_ID INTEGER UNSIGNED NOT NULL,
START_DATE DATETIME NOT NULL,
AMOUNT FLOAT NULL,
PRIMARY KEY(USERS_ID, ADVERT_ID, START_DATE),
INDEX TRANSACTION_FKIndex1(USERS_ID),
INDEX TRANSACTION_FKIndex2(ADVERT_ID),
INDEX TRANSACTION_FKIndex3(PAYMENT_TYPE_CODE),
FOREIGN KEY(USERS_ID)
REFERENCES USERS(ID)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
FOREIGN KEY(ADVERT_ID)
REFERENCES ADVERT(ID)
ON DELETE CASCADE
ON UPDATE NO ACTION
)
TYPE=InnoDB;
CREATE TABLE HOUSING (
ADVERT_ID INTEGER UNSIGNED NOT NULL,
PRIMARY KEY(ADVERT_ID),
FOREIGN KEY(ADVERT_ID)
REFERENCES ADVERT(ID)
ON DELETE CASCADE
ON UPDATE NO ACTION
)
TYPE=InnoDB;
Code between sessionFactory.openSession() and session.close():
// Save parent
this.baseDao.save((Advert)housing);
// Save child
housing = (Housing)this.baseDao.save(housing);
// Fetch transactions
((Advert)housing).getTransactions().size();
// Fetch advert owner
housing.getOwner();
Full stack trace of any exception that occurs:
Name and version of the database you are using:mysql 5.0
The generated SQL (show_sql=true):
Hibernate: insert into ADVERT (REFERENCE) values (?)
Hibernate: insert into HOUSING (advert_id) values (?)
Hibernate: select transactio_.USERS_ID, transactio_.ADVERT_ID, transactio_.START_DATE from TRANSACTION transactio_ where transactio_.USERS_ID=? and transactio_.ADVERT_ID=? and transactio_.START_DATE=?
Hibernate: select transactio_.USERS_ID, transactio_.ADVERT_ID, transactio_.START_DATE from TRANSACTION transactio_ where transactio_.USERS_ID=? and transactio_.ADVERT_ID=? and transactio_.START_DATE=?
Debug level Hibernate log excerpt:info
My first problem is that I need to save the advert before savaing the housing otherwise I get a FK violation constraint (which seems obvious if I where in pure jdbc but I expected that hibernate would save the "Advert part of Housing" before saving housing special fields and then inserting the advert_id fk).
My second problem is that my transactions set seems never to be populated while calling getTransactions() on "housing" object (neither is it on advert).
I guess it's a mapping issue. It's been a week that I'm trying to figure this out (I tried au_to join, extends, and many other mapping attibutes that seem to be in relation with joined-subclasses).
Any help would be appreciated