persistence@glassfish.java.net

Re: PrePersist method not being called

From: Tom Ware <tom.ware_at_oracle.com>
Date: Mon, 08 Jan 2007 13:55:42 -0500

Hi Jon,

  In addition to Guy's question about pre-update, I am wondering how
difficult it would be to package up your test case so we can take a look?

  The purpose of the javaagent is to allow us to run some code before
the main method runs. In our case we need a hook before the domain
classes are loaded. As a result, running programatically is not really
possible (unless Tomcat provides a hook) The suggested way of taking
advantage of OneToOne and ManyToOne lazy loading in an environment like
Tomcat is to take advantage of the static weaving feature I mention
below. That feature allows TopLink Essentials to preprocess your
classes and produced weaved versions of them. Those weaved versions are
capable of providing the lazy loading functionality without the javaagent.

-Tom

Guy Pelletier wrote:

>Hi Jon,
>
>I noticed there is a pre-update listener on the mapped superclass. Does it
>ever get called? Is it just the pre-persist that never executes?
>
>Cheers,
>Guy
>
>----- Original Message -----
>From: "Jon Miller" <jemiller_at_uchicago.edu>
>To: <persistence_at_glassfish.dev.java.net>
>Sent: Monday, January 08, 2007 1:00 PM
>Subject: Re: PrePersist method not being called
>
>
>
>
>>Thanks Tom. Yeah, I have all the classes listed there now. It still isn't
>>working though. I just tried a simpler test with the PrePersist method in
>>the top level class and it worked. I'll have to look into it further...
>>
>>Thanks for the info on weaving. I recently read about that. So far I just
>>been doing without it. I figure once I get further along I may need to
>>enable it if performance is an issue. One thing that I'm wondering about
>>the agent is: is it possible to somehow enable the agent programatically
>>in the program itself, or, does it have to be passed as a command-line
>>argument? I'm using TopLink with Tomcat and not using an EJB application
>>server. I like the idea of being able to deploy the web app self-contained
>>without having to make changes to the web server configuration such as
>>passing command-line arguments to the JVM.
>>
>>Jon
>>
>>----- Original Message -----
>>From: "Tom Ware" <tom.ware_at_oracle.com>
>>To: <persistence_at_glassfish.dev.java.net>
>>Sent: Monday, January 08, 2007 8:28 AM
>>Subject: Re: PrePersist method not being called
>>
>>
>>
>>
>>>Hi Jon,
>>>
>>> Are you still seeing the problem now that you have listed AuditObject in
>>>your persistence.xml?
>>>
>>>In Java SE, the JPA specification says that portable applications must
>>>list the classes that will be used in the persistence.xml either with
>>><class> element, by referring to them in a file referenced by a
>>><mapping-file> element, or by placing them in a file referenced by a
>>><jar-file> element. As a result, in Java SE depending on how your
>>>persistence.xml looks, we may not automatically discover your classes.
>>>
>>> In some Java SE Environments TopLink Essentials will be able to
>>>auto-discover if you use the <exclude-unlisted-classes> element in your
>>>persistence.xml and set it to false.
>>>
>>> FYI: You have asked a couple of questions about the javaagent, so I'll
>>>give you an idea what the purpose of the agent is. In TopLink
>>>Essentials, we use the javaagent to dynamically weave classes that have
>>>OneToOne or ManyToOne mappings with FetchType LAZY. The weaving allows
>>>us to actually retrieve the elements referenced by those mappings in a
>>>LAZY manner. For those that do not wish to use the agent (or cannot use
>>>it), there is also the option of using a preprocessing step for this
>>>weaving. If you are interested in that step, take a look at the section
>>>of the following document entitled, "Static Weaving Using the StaticWeave
>>>Class on the Command Line":
>>>
>>>http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-extensions.html#LazyLoading
>>>
>>>-Tom
>>>
>>>Jon Miller wrote:
>>>
>>>
>>>
>>>>I thought I found what might have been the problem on my side. I wasn't
>>>>listing AuditObject in my persistence.xml. Initially, I was thinking that
>>>>you only would have to list the subclasses that you are using directly
>>>>and that it would automatically add in the superclasses for you. I found
>>>>out that this doesn't appear to be the case though (at least in
>>>>standalone mode). Another thing worth mentioning is that the AuditObject
>>>>class is in a different jar file. I'm not sure if that would make a
>>>>difference or not. There's only one persistence.xml, but, the classes are
>>>>split between two jar files.
>>>>
>>>>Jon
>>>>
>>>>----- Original Message -----
>>>>From: "Jon Miller" <jemiller_at_uchicago.edu>
>>>>To: <persistence_at_glassfish.dev.java.net>
>>>>Sent: Friday, January 05, 2007 6:13 PM
>>>>Subject: Re: PrePersist method not being called
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>>OK, I tested it and it works with Hibernate, but, I receive the
>>>>>following error with TopLink. The prePersist method is supposed to be
>>>>>called which sets the lastWriteTime field. This isn't happening, so,
>>>>>it's causing an exception since that field is NOT NULL.
>>>>>
>>>>> [junit] Caused by: Exception [TOPLINK-4002] (Oracle TopLink
>>>>>Essentials - 9.1 (Build b30)): oracle.toplink.essentials
>>>>>.exceptions.DatabaseException
>>>>> [junit] Internal Exception: java.sql.SQLException:
>>>>>[SKATE\SQLEXPRESS]Cannot insert the value NULL into column 'LastW
>>>>>riteTime', table 'Schedules.dbo.Person'; column does not allow nulls.
>>>>>INSERT fails.Error Code: 515
>>>>> [junit] Call:INSERT INTO Person (Department, CreationUserName,
>>>>>FirstName, LastName, LastWriteTime, Name, LastWriteUs
>>>>>erName, MiddleName, TelephoneNumber, Title, CreationTime, Curriculum,
>>>>>Address, UserName, EmailAddress, Organization, Cla
>>>>>ss) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
>>>>> [junit] bind => [null, null, Jonathan, Miller, null, Jonathan
>>>>>Eric Miller, null, Eric, null, null, null, null, n
>>>>>ull, jemiller, null, null, Schedules.Persistence.Entity.User]
>>>>>
>>>>>Jon
>>>>>
>>>>>----- Original Message -----
>>>>>From: "Jon Miller" <jemiller_at_uchicago.edu>
>>>>>To: <persistence_at_glassfish.dev.java.net>
>>>>>Sent: Friday, January 05, 2007 5:47 PM
>>>>>Subject: Re: PrePersist method not being called
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>>OK, I tested it with V2 build 30. It still isn't getting called. I'm
>>>>>>not using the agent at present. Would that matter? I'm wondering if the
>>>>>>problem is that the PrePersist method is in a MappedSuperclass? I think
>>>>>>that's a valid thing to do though. I think the Javadocs mention it if I
>>>>>>remember correctly. I'm going to test it again with Hibernate, just to
>>>>>>make sure I'm not doing something else wrong and that it does indeed
>>>>>>work with Hibernate and not TopLink.
>>>>>>
>>>>>>Jon
>>>>>>
>>>>>>----- Original Message -----
>>>>>>From: "Tom Ware" <tom.ware_at_oracle.com>
>>>>>>To: <persistence_at_glassfish.dev.java.net>
>>>>>>Sent: Thursday, January 04, 2007 2:10 PM
>>>>>>Subject: Re: PrePersist method not being called
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>Hi Jon,
>>>>>>>
>>>>>>>Do you see the same behavior on the latest builds of TopLink
>>>>>>>essentials (e.g. V2 build 30)? There have been quite a lot of
>>>>>>>changes since the end of August (060830).
>>>>>>>
>>>>>>>You can get the latest version at:
>>>>>>>
>>>>>>>https://glassfish.dev.java.net/downloads/persistence/JavaPersistence.html
>>>>>>>
>>>>>>>-Tom
>>>>>>>
>>>>>>>Jon Miller wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>>Hi all,
>>>>>>>>
>>>>>>>>I'm using the version of Toplink Essentials that comes with NetBeans
>>>>>>>>5.5. I have a class which defines a PrePersist method
>>>>>>>>(AuditObject.prePersist()) which sets some values in an object
>>>>>>>>(namely a timestamp which is a NOT NULL value). I'm finding that this
>>>>>>>>method isn't being called when I attempt to persist an Item object
>>>>>>>>(subclass of AuditObject). It works fine if I use Hibernate's
>>>>>>>>implementation of JPA. Does anyone know what I might be doing wrong
>>>>>>>>or if this is a known issue? So far I haven't been using the
>>>>>>>>javaagent. However, I just tried it with the agent to see if that
>>>>>>>>might be the problem, but, it didn't make a difference. The following
>>>>>>>>is the exception that I'm receiving.
>>>>>>>>
>>>>>>>>Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2006.8 (Build
>>>>>>>>060830)): oracle.toplink.essentials.exceptions.DatabaseException
>>>>>>>>Internal Exception: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot
>>>>>>>>insert the value NULL into column 'LastWriteTime', table
>>>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT
>>>>>>>>fails.Error Code: 515
>>>>>>>>Call:INSERT INTO Item (Name, CreationUserName, Description,
>>>>>>>>LastWriteUserName, LastWriteTime, CreationTime) VALUES (?, ?, ?, ?,
>>>>>>>>?, ?)
>>>>>>>> bind => [testSaveItem Wed Jan 03 14:43:08 CST 2007, null,
>>>>>>>>Description, null, null, null]
>>>>>>>>Query:InsertObjectQuery([id = null, name = "testSaveItem Wed Jan 03
>>>>>>>>14:43:08 CST 2007", description = "Description"])
>>>>>>>>javax.persistence.RollbackException: Exception [TOPLINK-4002] (Oracle
>>>>>>>>TopLink Essentials - 2006.8 (Build 060830)):
>>>>>>>>oracle.toplink.essentials.exceptions.DatabaseException
>>>>>>>>Internal Exception: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot
>>>>>>>>insert the value NULL into column 'LastWriteTime', table
>>>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT
>>>>>>>>fails.Error Code: 515
>>>>>>>>Call:INSERT INTO Item (Name, CreationUserName, Description,
>>>>>>>>LastWriteUserName, LastWriteTime, CreationTime) VALUES (?, ?, ?, ?,
>>>>>>>>?, ?)
>>>>>>>> bind => [testSaveItem Wed Jan 03 14:43:08 CST 2007, null,
>>>>>>>>Description, null, null, null]
>>>>>>>>Query:InsertObjectQuery([id = null, name = "testSaveItem Wed Jan 03
>>>>>>>>14:43:08 CST 2007", description = "Description"])
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:109)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.ejb.cmp3.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:45)
>>>>>>>> at
>>>>>>>>edu.uchicago.at.reservations.ReservationsService.saveItem(ReservationsService.java:254)
>>>>>>>> at
>>>>>>>>edu.uchicago.at.reservations.ReservationsServiceTest.testSaveGetAndRemoveItem(ReservationsServiceTest.java:44)
>>>>>>>>Caused by: Exception [TOPLINK-4002] (Oracle TopLink Essentials -
>>>>>>>>2006.8 (Build 060830)):
>>>>>>>>oracle.toplink.essentials.exceptions.DatabaseException
>>>>>>>>Internal Exception: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot
>>>>>>>>insert the value NULL into column 'LastWriteTime', table
>>>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT
>>>>>>>>fails.Error Code: 515
>>>>>>>>Call:INSERT INTO Item (Name, CreationUserName, Description,
>>>>>>>>LastWriteUserName, LastWriteTime, CreationTime) VALUES (?, ?, ?, ?,
>>>>>>>>?, ?)
>>>>>>>> bind => [testSaveItem Wed Jan 03 14:43:08 CST 2007, null,
>>>>>>>>Description, null, null, null]
>>>>>>>>Query:InsertObjectQuery([id = null, name = "testSaveItem Wed Jan 03
>>>>>>>>14:43:08 CST 2007", description = "Description"])
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:295)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:639)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:688)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:477)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:437)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:675)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:213)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:199)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:331)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:176)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:190)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:457)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.queryframework.InsertObjectQuery.executeCommit(InsertObjectQuery.java:74)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedWrite(DatabaseQueryMechanism.java:635)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedInsert(DatabaseQueryMechanism.java:599)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:495)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.queryframework.WriteObjectQuery.executeCommitWithChangeSet(WriteObjectQuery.java:130)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:283)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:67)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:536)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:123)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:95)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2218)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:894)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:254)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:175)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:2638)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1030)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:357)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1112)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:82)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:842)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:90)
>>>>>>>> ... 18 more
>>>>>>>>Caused by: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot insert the
>>>>>>>>value NULL into column 'LastWriteTime', table
>>>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT
>>>>>>>>fails.
>>>>>>>> at com.inet.tds.a.a(Unknown Source)
>>>>>>>> at com.inet.tds.c.new(Unknown Source)
>>>>>>>> at com.inet.tds.c.executeUpdate(Unknown Source)
>>>>>>>> at
>>>>>>>>oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:632)
>>>>>>>> ... 51 more
>>>>>>>>
>>>>>>>>// AuditObject.java
>>>>>>>>package edu.uchicago.at.common.persistence.entity;
>>>>>>>>
>>>>>>>>import java.io.Serializable;
>>>>>>>>import java.util.Date;
>>>>>>>>import java.util.logging.Logger;
>>>>>>>>import javax.persistence.Column;
>>>>>>>>import javax.persistence.MappedSuperclass;
>>>>>>>>import javax.persistence.PrePersist;
>>>>>>>>import javax.persistence.PreUpdate;
>>>>>>>>import javax.persistence.Temporal;
>>>>>>>>import javax.persistence.TemporalType;
>>>>>>>>
>>>>>>>>@MappedSuperclass
>>>>>>>>public abstract class AuditObject implements Serializable {
>>>>>>>> private Date creationTime;
>>>>>>>> private String creationUserName;
>>>>>>>> private Date lastWriteTime;
>>>>>>>> private String lastWriteUserName;
>>>>>>>> private static Logger logger = Logger.getLogger(
>>>>>>>> AuditObject.class.getName());
>>>>>>>>
>>>>>>>> @Column(name="CreationTime", nullable=false)
>>>>>>>> @Temporal(TemporalType.TIMESTAMP)
>>>>>>>> public Date getCreationTime() {
>>>>>>>> return creationTime;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setCreationTime(Date creationTime) {
>>>>>>>> this.creationTime = creationTime;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Column(name="CreationUserName", columnDefinition="nvarchar(255)")
>>>>>>>> public String getCreationUserName() {
>>>>>>>> return creationUserName;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setCreationUserName(String creationUserName) {
>>>>>>>> this.creationUserName = creationUserName;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Column(name="LastWriteTime", nullable=false)
>>>>>>>> @Temporal(TemporalType.TIMESTAMP)
>>>>>>>> public Date getLastWriteTime() {
>>>>>>>> return lastWriteTime;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setLastWriteTime(Date lastWriteTime) {
>>>>>>>> this.lastWriteTime = lastWriteTime;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Column(name="LastWriteUserName",
>>>>>>>>columnDefinition="nvarchar(255)")
>>>>>>>> public String getLastWriteUserName() {
>>>>>>>> return lastWriteUserName;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setLastWriteUserName(String lastWriteUserName) {
>>>>>>>> this.lastWriteUserName = lastWriteUserName;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @PrePersist
>>>>>>>> public void prePersist() {
>>>>>>>> Date d = new Date();
>>>>>>>> setCreationTime(d);
>>>>>>>> setLastWriteTime(d);
>>>>>>>> }
>>>>>>>>
>>>>>>>> @PreUpdate
>>>>>>>> public void preUpdate() {
>>>>>>>> Date d = new Date();
>>>>>>>> setLastWriteTime(d);
>>>>>>>> }
>>>>>>>>}
>>>>>>>>
>>>>>>>>// Item.java
>>>>>>>>package edu.uchicago.at.reservations.persistence.entity;
>>>>>>>>
>>>>>>>>import edu.uchicago.at.common.persistence.entity.AuditObject;
>>>>>>>>import java.util.ArrayList;
>>>>>>>>import java.util.Collection;
>>>>>>>>import javax.persistence.Column;
>>>>>>>>import javax.persistence.Entity;
>>>>>>>>import javax.persistence.GeneratedValue;
>>>>>>>>import javax.persistence.GenerationType;
>>>>>>>>import javax.persistence.Id;
>>>>>>>>import javax.persistence.JoinColumn;
>>>>>>>>import javax.persistence.JoinTable;
>>>>>>>>import javax.persistence.ManyToMany;
>>>>>>>>import javax.persistence.Table;
>>>>>>>>
>>>>>>>>@Entity
>>>>>>>>@Table(name="Item")
>>>>>>>>public class Item extends AuditObject {
>>>>>>>> private String description;
>>>>>>>> private Integer id;
>>>>>>>> private String name;
>>>>>>>> private Collection<Reservation> reservations = new
>>>>>>>>ArrayList<Reservation>();
>>>>>>>> private Collection<Item> subItems = new ArrayList<Item>();
>>>>>>>> private Collection<Item> superItems = new ArrayList<Item>();
>>>>>>>>
>>>>>>>> public Item() {
>>>>>>>> }
>>>>>>>>
>>>>>>>> public Item(String name) {
>>>>>>>> setName(name);
>>>>>>>> }
>>>>>>>>
>>>>>>>> public boolean contains(Item item) {
>>>>>>>> for(Item i : subItems) {
>>>>>>>> if (i.id == item.id) {
>>>>>>>> return true;
>>>>>>>> }
>>>>>>>> if (i.contains(item)) {
>>>>>>>> return true;
>>>>>>>> }
>>>>>>>> }
>>>>>>>> return false;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Column(name="Description", columnDefinition="nvarchar(max)")
>>>>>>>> public String getDescription() {
>>>>>>>> return description;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setDescription(String description) {
>>>>>>>> this.description = description;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Id
>>>>>>>> @GeneratedValue(strategy = GenerationType.IDENTITY)
>>>>>>>> @Column(name="Id")
>>>>>>>> public Integer getId() {
>>>>>>>> return id;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setId(Integer id) {
>>>>>>>> this.id = id;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Column(name="Name", columnDefinition="nvarchar(255)")
>>>>>>>> public String getName() {
>>>>>>>> return name;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setName(String name) {
>>>>>>>> this.name = name;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @ManyToMany(mappedBy="items")
>>>>>>>> public Collection<Reservation> getReservations() {
>>>>>>>> return reservations;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setReservations(Collection<Reservation> reservations)
>>>>>>>>{
>>>>>>>> this.reservations = reservations;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @ManyToMany
>>>>>>>> @JoinTable(name="ItemItem",
>>>>>>>>joinColumns={_at_JoinColumn(name="ItemId")},
>>>>>>>> inverseJoinColumns={_at_JoinColumn(name="SubItemId")})
>>>>>>>> public Collection<Item> getSubItems() {
>>>>>>>> return subItems;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setSubItems(Collection<Item> subItems) {
>>>>>>>> this.subItems = subItems;
>>>>>>>> }
>>>>>>>>
>>>>>>>> @ManyToMany(mappedBy="subItems")
>>>>>>>> public Collection<Item> getSuperItems() {
>>>>>>>> return superItems;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public void setSuperItems(Collection<Item> superItems) {
>>>>>>>> this.superItems = superItems;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public String toString() {
>>>>>>>> StringBuilder sb = new StringBuilder();
>>>>>>>> sb.append("[");
>>>>>>>> sb.append(String.format("id = %d", id));
>>>>>>>> sb.append(String.format(", name = \"%s\"", name));
>>>>>>>> sb.append(String.format(", description = \"%s\"",
>>>>>>>>description));
>>>>>>>> sb.append("]");
>>>>>>>> return sb.toString();
>>>>>>>> }
>>>>>>>>}
>>>>>>>>
>>>>>>>>Jon
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>

-- 
Tom Ware
Principal Software Engineer
Oracle Canada Inc.
Direct: (613) 783-4598
Email: tom.ware_at_oracle.com