Hibernate version: 3.2.3
Name and version of the database you are using: MySQL 5
I have a 'document' table that is hierarchical:
Code:
document {
document_id PK,
parent_id FK(document),
...
}
The way our document tree is set up is with a single 'root' document, with document_id = 1. All other documents are under the root document, in a tree structure.
Because we frequently need to know all descendents or ancestors of a particular document, we maintain a link table:
Code:
document_ancestry_link {
document_id FK(document),
ancestor_id FK(document)
}
This table has rows for each document, linking to each of its 'ancestors' (its parent, that parent's parent, ..., the root doc (1)).
This allows us to map associations to a document's 'ancestors' or 'descendents'. Here's the mapping, with annotations, for ancestors, on the Document class:
Code:
@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(
name="document_ancestry_link",
joinColumns={@JoinColumn(name="document_id")},
inverseJoinColumns={@JoinColumn(name="ancestor_id")}
)
public Set<Document> getAncestors() {
return this.ancestors;
}
The children of the root document are important, called a 'collection'. We frequently want to find out what collection a document is in, or run queries by collection.
We are trying to make this simple by creating a view, called 'document_collection', which is essentially a link table from any document to its collection document:
Code:
CREATE OR REPLACE VIEW document_collection AS
SELECT d.document_id as document_id, a.document_id as collection_id
FROM document d
JOIN document_ancestry_link l ON d.document_id = l.document_id
JOIN document a ON l.ancestor_id = a.document_id
WHERE a.parent_id = 1;
I'd like to map this in the Document object, so I have a getCollection() method that returns the collection for any document.
My problem is that no matter how I map it, I can't get Hibernate not to try to delete from the view when I delete a document. Here's what I have currently:
Code:
@ManyToOne(fetch=FetchType.LAZY)
@JoinTable(name="document_collection", joinColumns=@JoinColumn(name="document_id"), inverseJoinColumns=@JoinColumn(name="publication_id"))
public Document getCollection()
{
return this.collection;
}
I can add 'updatable=false, insertable=false' to the @JoinColumn, but that doesn't seem to affect deletes at all. I feel like there needs to be a 'deletable=false' option, which there isn't. Here's the relevant part of the log, with the exception:
Quote:
2007-06-08 08:36:35,365 [main] DEBUG org.hibernate.SQL - delete from document_ancestry_link where document_id=?
2007-06-08 08:36:35,365 [main] DEBUG org.hibernate.SQL - delete from document_collection where document_id=?
2007-06-08 08:36:35,365 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1395, SQLState: HY000
2007-06-08 08:36:35,365 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Can not delete from join view 'servicetest.document_publication'
2007-06-08 08:36:35,365 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: could not delete: [com.blah.Document#5]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2541)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2697)
at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:74)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at com.blah.DocumentManager.deleteDocument(DocumentManager.java:1348)
at
...
Caused by: java.sql.SQLException: Can not delete from join view 'document_collection'
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2941)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1623)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1715)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3249)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1268)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1541)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1455)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1440)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2523)
... 35 more
Notice that Hibernate deletes from document_ancestry_link, because of the ancestors association, which is all that needs to happen, but then it tries to delete from the view, also.
How can I tell Hibernate not to try to delete from the view??