Hi,
I am fairly new to hibernate but have searched extensively to find my answer and came up short. I assume I am making some simple configuration mistake.
I have narrowed this down to a simple Invoice type application to make it easy for everyone to understand, though the code is obviously unrealistic.
I have mapped the invoice and its line items in a single mapping file using composite-element. The mapping file is as follows.
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.ftid.nplusone">
<class name="Invoice" table="INVOICE" lazy="false" dynamic-update="true">
<id name="invoiceId" type="long" column="INVOICE_ID"/>
<property name="customerName" type="string">
<column name="CUSTOMER_NAME"></column>
</property>
<set name="lineItems" table="INVOICE_ITEM" lazy="false">
<key column="INVOICE_ID"/>
<composite-element class="com.ftid.nplusone.InvoiceItem">
<property name="sequenceNumber" column="SEQ" type="long"/>
<property name="sku" column="SKU" type="string"/>
<property name="description" column="DESCRIPTION" type="string"/>
</composite-element>
</set>
</class>
</hibernate-mapping>
My java code looks like this:
Code:
package com.ftid.nplusone;
import java.util.Set;
import java.io.Serializable;
/**
* Invoice is an obviously contrived example of a common and simple concept.
*/
public class Invoice implements Serializable, Comparable<Invoice> {
private long invoiceId;
private String customerName;
private Set<InvoiceItem> lineItems;
public long getInvoiceId() {
return invoiceId;
}
public void setInvoiceId(long invoiceId) {
this.invoiceId = invoiceId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public Set<InvoiceItem> getLineItems() {
return lineItems;
}
public void setLineItems(Set<InvoiceItem> lineItems) {
this.lineItems = lineItems;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Invoice invoice = (Invoice) o;
if (invoiceId != invoice.invoiceId) {
return false;
}
return true;
}
public int hashCode() {
return (int) (invoiceId ^ (invoiceId >>> 32));
}
public int compareTo(Invoice that) {
int retVal = 0;
if (this.invoiceId < that.invoiceId) {
retVal = -1;
}
else if (this.invoiceId > that.invoiceId) {
retVal = 1;
}
return retVal; //TODO: Implement this method.
}
}
Code:
package com.ftid.nplusone;
import java.io.Serializable;
/**
* InvoiceItem is a line item for an invoice in this simplistic example.
*/
public class InvoiceItem implements Serializable, Comparable<InvoiceItem> {
private long invoiceId;
private long sequenceNumber;
private String sku;
private String description;
public long getInvoiceId() {
return invoiceId;
}
public void setInvoiceId(long invoiceId) {
this.invoiceId = invoiceId;
}
public long getSequenceNumber() {
return sequenceNumber;
}
public void setSequenceNumber(long sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
public String getSku() {
return sku;
}
public void setSku(String sku) {
this.sku = sku;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
InvoiceItem that = (InvoiceItem) o;
if (invoiceId != that.invoiceId) {
return false;
}
if (sequenceNumber != that.sequenceNumber) {
return false;
}
return true;
}
public int hashCode() {
int result;
result = (int) (invoiceId ^ (invoiceId >>> 32));
result = 31 * result + (int) (sequenceNumber ^ (sequenceNumber >>> 32));
return result;
}
public int compareTo(InvoiceItem that) {
int retVal = 0;
if (this.invoiceId < that.invoiceId) {
retVal = -1;
}
else if (this.invoiceId > that.invoiceId) {
retVal = 1;
}
else {
if (this.sequenceNumber < that.sequenceNumber) {
retVal = -1;
}
else if (this.sequenceNumber > that.sequenceNumber) {
retVal = 1;
}
}
return retVal;
}
}
I use the followiing query for the fetch.
Code:
select i from Invoice i left outer join fetch i.lineItems lineItems
The problem I have is that for any invoice with N line items, I get N Invoice instances, each fully formed with the complete list of line items.
Note that I am using lazy="false".
Any help you can provide to get this to return a single fully formed instance of each Invoice would be greatly appreciated.
Scott