I am having a strange, to me, error saving or loading a set. What I am doing works perfect with a different set of classes, but when I do it here I get a null value from getItems() , and new items don't get their fk set.
I am using the GenericDAO template pattern that was linked to from the wiki. It works great for all the other classes. These two work fine if I do them separately, but when I get the items for the invoice (after saving them separately and retrieving to a new object), the set is still null.
Hibernate version: 3
Mapping documents: Invoice.hbm.xml, InvoiceItem.hbm.xml
Code between sessionFactory.openSession() and session.close():
[ from a filter ]
sf.getCurrentSession().beginTransaction();
sf.getCurrentSession().setCacheMode(CacheMode.NORMAL);
sf.getCurrentSession().setFlushMode(FlushMode.COMMIT);
chain.doFilter() // my stuff
sf.getCurrentSession().getTransaction().commit();
Name and version of the database you are using:
MySQL 5
The generated SQL (show_sql=true):
Code:
13:42:58,485 DEBUG SQL:346 - insert into invoice (user_id, status, ship_name, card_name, card_number, card_exp_year, card_exp_month, card_type, ship_address_id, bill_address_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
13:42:58,486 DEBUG LongType:79 - binding '2' to parameter: 1
13:42:58,489 DEBUG StringType:79 - binding 'WAITING' to parameter: 2
13:42:58,489 DEBUG StringType:79 - binding 'ShipName' to parameter: 3
13:42:58,494 DEBUG StringType:79 - binding 'CARD-NAME' to parameter: 4
13:42:58,494 DEBUG StringType:79 - binding 'CARD-NUMBER' to parameter: 5
13:42:58,495 DEBUG StringType:79 - binding '2008' to parameter: 6
13:42:58,495 DEBUG StringType:79 - binding '06' to parameter: 7
13:42:58,496 DEBUG StringType:79 - binding 'VISA' to parameter: 8
13:42:58,496 DEBUG LongType:79 - binding '21' to parameter: 9
13:42:58,497 DEBUG LongType:79 - binding '22' to parameter: 10
13:42:58,497 DEBUG LongType:79 - binding '4' to parameter: 11
13:42:58,499 DEBUG SQL:346 - insert into invoice_item (quantity, price, description, bouquet_id, invoice_id, item_id, id) values (?, ?, ?, ?, ?, ?, ?)
13:42:58,500 DEBUG LongType:79 - binding '3' to parameter: 1
13:42:58,501 DEBUG DoubleType:79 - binding '200.75' to parameter: 2
13:42:58,501 DEBUG StringType:79 - binding 'test item' to parameter: 3
13:42:58,508 DEBUG LongType:71 - binding null to parameter: 4
13:42:58,509 DEBUG LongType:71 - binding null to parameter: 5
13:42:58,510 DEBUG LongType:79 - binding '100' to parameter: 6
13:42:58,510 DEBUG LongType:79 - binding '2' to parameter: 7
13:42:58,535 WARN JDBCExceptionReporter:71 - SQL Error: 1048, SQLState: 23000
13:42:58,536 ERROR JDBCExceptionReporter:72 - Column 'invoice_id' cannot be null
13:42:58,539 ERROR AbstractFlushingEventListener:299 - Could not synchronize database state with session
The HBM filesSome of the simple proprites have been stripped out to shorten it up, but they all work. The many-to-ones work, putting items in the address table just like they should. I have left the
invoice_id column on the invoice_items table nullable (in the hbm) so that you can see the error. If I don't do that, I get an error about not null property being set to null or transient.
Code:
<hibernate-mapping>
<class name="model.Invoice" table="invoice" lazy="false">
<id name="id" column="id" unsaved-value="null">
<generator class="increment"/>
</id>
<property name="userId" column="user_id" not-null="true"/>
<property name="status" column="status" not-null="true"/>
...
<property name="dateCreated" column="date_created" insert="false" update="false" not-null="true"/>
<many-to-one name="shipAddress" column="ship_address_id" lazy="false"
unique="true" cascade="all"
/>
<many-to-one name="billAddress" column="bill_address_id" lazy="false"
unique="true" cascade="all"
/>
<set name="items" lazy="true" inverse="true" cascade="all">
<key column="invoice_id" />
<one-to-many class="model.InvoiceItem"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="model.InvoiceItem" table="invoice_item" lazy="false">
<id name="id" column="id" unsaved-value="null">
<generator class="increment"/>
</id>
<property name="quantity" column="quantity" not-null="true"/>
<property name="price" column="price" not-null="true"/>
<property name="description" column="description" not-null="true"/>
<property name="bouquetId" column="bouquet_id" />
<property name="invoiceId" column="invoice_id"/>
<property name="itemId" column="item_id" not-null="false"/>
</class>
</hibernate-mapping>
The JavaCode:
public class Invoice implements Serializable {
private Long id;
private Long userId;
private double total;
private Date dateCreated;
private String status;
...
private Address shipAddress;
private Address billAddress;
private Set<InvoiceItem> items;
public Invoice() {}
// AUTOGENERATED ----------------------------------------
public Long getId() {
return id;
}
....
public class InvoiceItem implements Serializable {
private Long id;
private Long invoiceId;
private Long bouquetId;
private Long itemId;
private String description;
private long quantity;
private double price;
public InvoiceItem() {}
//-- generate --------------
public Long getId() {
return id;
}
...
The code that I am runningThis is just some simple test code in a jsp.
Code:
InvoiceDAO ivdao = DAOFactory.getInvoiceDAO();
Invoice iv = new Invoice();
iv.setUserId(2L);
Address addr1 = new Address();
Address addr2 = new Address();
addr1.setStreet("one place");
addr1.setCity("san anselmo");
addr1.setState("CA");
addr1.setZip("11111");
addr2.setStreet("wtf street");
addr2.setCity("san Rafael");
addr2.setState("FR");
addr2.setZip("doh");
iv.setShipName("ShipName");
iv.setStatus("WAITING");
iv.setTotal(0);
iv.setShipAddress(addr1);
iv.setBillAddress(addr2);
InvoiceItem itm = new InvoiceItem();
itm.setDescription("test item");
itm.setItemId(100L);
itm.setPrice(200.75);
itm.setQuantity(3);
itm.setInvoiceId(iv.getId());
HashSet<InvoiceItem> set = new HashSet<InvoiceItem>();
set.add(itm);
iv.setItems(set);
ivdao.makePersistent(iv);
Any clues as to why this is happening. it is driving me completely mad. I assume there is some fundamental problem that exists but that hibernate is not telling me about (like long vs. Long) that makes this not work.
Thanks,
Andrew Backer