-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Having trouble with bulk update/delete on joined subclasses
PostPosted: Tue Jan 09, 2007 2:27 pm 
Newbie

Joined: Tue Jan 09, 2007 1:40 pm
Posts: 2
I'm having trouble doing bulk updates and deletes on joined subclass entities using MS SQL Server 2005. I get an error from the database saying the generated SQL has an ambiguous column name when I include a where clause that includes the joined subclass' id property.

Hibernate version:
3.2.1
Mapping documents:
Code:
  <class name="test.A" table="A">
    <id name="id" type="integer" />
  </class>
  <joined-subclass name="test.B" table="B" extends="test.A">
    <key column="id" />
    <property name="myValue" type="integer" />
  </joined-subclass>

Code between sessionFactory.openSession() and session.close():
Code:
Transaction t = s.beginTransaction();
Query q = s.createQuery("update B b set b.myValue=10 where b.id=1");
int count = q.executeUpdate();
t.commit();


Full stack trace of any exception that occurs:
Code:
org.hibernate.exception.GenericJDBCException: could not insert/select ids for bulk update
   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.hql.ast.exec.MultiTableUpdateExecutor.execute(MultiTableUpdateExecutor.java:127)
   at org.hibernate.hql.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:396)
   at org.hibernate.engine.query.HQLQueryPlan.performExecuteUpdate(HQLQueryPlan.java:259)
   at org.hibernate.impl.SessionImpl.executeUpdate(SessionImpl.java:1141)
   at org.hibernate.impl.QueryImpl.executeUpdate(QueryImpl.java:94)
   at test.MyTest.main(MyTest.java:51)
Caused by: java.sql.SQLException: Ambiguous column name 'id'.
   at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:364)
   at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2754)
   at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2195)
   at net.sourceforge.jtds.jdbc.TdsCore.getMoreResults(TdsCore.java:620)
   at net.sourceforge.jtds.jdbc.JtdsStatement.processResults(JtdsStatement.java:483)
   at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:445)
   at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeUpdate(JtdsPreparedStatement.java:402)
   at org.hibernate.hql.ast.exec.MultiTableUpdateExecutor.execute(MultiTableUpdateExecutor.java:118)
   ... 5 more


Name and version of the database you are using:
Microsoft SQL Server 2005

The generated SQL (show_sql=true):
Code:
insert into #B select b0_.id as id from B b0_ inner join A b0_1_ on b0_.id=b0_1_.id where id=1


A similar problem occurs when I trying to do bulk deletes with a where clause that includes the id property ("delete B b where b.id=1").

This same code works correctly when I use Sybase ASA 9.0.2 as my database. Hibernate generates the same SQL, but Sybase ASA doesn't complain about ambiguity. MS SQL Server just doesn't seem to allow the unqualified reference to "id" in the where clause in this case. It seems to require "where b0_.id=1" instead of "where id=1".

I don't see anything in the reference documentation that suggests that I'm doing something that's unsupported or wrong. Can anyone help me out? I would really appreciate it.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 24, 2007 5:29 pm 
Newbie

Joined: Tue Jan 09, 2007 1:40 pm
Posts: 2
I traced this into org.hibernate.hql.ast.tree.FromElementType.toColumns() where it is deciding whether to qualify the column reference with the tableAlias. In my case, where I'm doing update and delete statements with a joined subclass, I believe it incorrectly chooses not to qualify the column reference. It seems to me that when the FromElementType class is dealing with the WHERE clause of an UPDATE or DELETE statement and is dealing with a joined subclass entity, it should qualify the column reference.

I made the following modifications to FromElementType locally to try it out:

Code:
~/src/hibernate-trunk> svn diff src/org/hibernate/hql/ast/tree/FromElementType.java
Index: src/org/hibernate/hql/ast/tree/FromElementType.java
===================================================================
--- src/org/hibernate/hql/ast/tree/FromElementType.java (revision 11097)
+++ src/org/hibernate/hql/ast/tree/FromElementType.java (working copy)
@@ -343,6 +343,16 @@
                                        return propertyMapping.toColumns( tableAlias, path );
                                }
                        }
+            else if ( fromElement.getWalker().getStatementType() == HqlSqlTokenTypes.UPDATE &&
+                      fromElement.getEntityPersister() instanceof JoinedSubclassEntityPersister &&
+                      fromElement.getWalker().getCurrentClauseType() == HqlSqlTokenTypes.WHERE) {
+                return propertyMapping.toColumns( tableAlias, path );
+            }
+            else if ( fromElement.getWalker().getStatementType() == HqlSqlTokenTypes.DELETE &&
+                      fromElement.getEntityPersister() instanceof JoinedSubclassEntityPersister &&
+                      fromElement.getWalker().getCurrentClauseType() == HqlSqlTokenTypes.WHERE) {
+                return propertyMapping.toColumns( tableAlias, path );
+            }
                        else {
                                String[] columns = propertyMapping.toColumns( path );
                                log.trace( "Using non-qualified column reference [" + path + " -> (" + ArrayHelper.toString( columns ) + ")]" );


This fixes the problem I am seeing and as a bonus, it hasn't broken anything else in my application (at least not that I've found yet). I've run it against SQL Server 2005 and Sybase ASA 9.0.2/10.. The generated SQL is now:

Code:
insert into #B select b0_.id as id from B b0_ inner join A b0_1_ on b0_.id=b0_1_.id where b0_.id=1
update B set myValue=10 where (id) IN (select id from #B)


which SQL Server accepts.

This is my first foray into the inner workings of Hibernate. Can anyone give me any feedback about whether or not I'm on the right track? I don't pretend to know if this change is complete and correct in all cases, or even if it's in keeping with the intent of the method. I would really appreciate if an expert would look at it and see if I'm on to something. I'd be happy to provide simple working code that causes the exception I'm getting from SQL Server.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.