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
>>>>
>>>
>>
>