I have an entity (A) which has an embedded key and a n:1 association (B).Both entity have some key columns with the same name.
As soon as autoFetch optimizes (it is not an autoFetch problem) the query by making the association eager fetched the column names are no longer unique, and the generated idBindSql in IdBinderEmbedded is missing the table alias - which creates an invalid sql then.
I am not sure if my patch here is a hack, at least it tries to get the dbAlias from "somewhere" in case the deploy itself does not define one, and then, when building the idBindSql one is available to prefix the column.
Index: ../ebean/src/com/avaje/ebean/server/deploy/BeanProperty.java===================================================================--- ../ebean/src/com/avaje/ebean/server/deploy/BeanProperty.java (revision 168)+++ ../ebean/src/com/avaje/ebean/server/deploy/BeanProperty.java Fri Mar 13 10:47:45 CET 2009@@ -248,7 +247,12 @@ this.dbColumn = deploy.getDbColumn(); this.dbFullName = deploy.getDbFullName();+ if (deploy.getDbTableAlias() == null) {+ this.dbTableAlias = descriptor.getBaseTableAlias();+ }+ else {- this.dbTableAlias = deploy.getDbTableAlias();+ this.dbTableAlias = deploy.getDbTableAlias();+ } this.sqlFormulaJoin = deploy.getSqlFormulaJoin(); this.sqlFormulaSelect = deploy.getSqlFormulaSelect(); this.formula = sqlFormulaSelect != null;Index: ../ebean/src/com/avaje/ebean/server/deploy/id/IdBinderEmbedded.java===================================================================--- ../ebean/src/com/avaje/ebean/server/deploy/id/IdBinderEmbedded.java (revision 168)+++ ../ebean/src/com/avaje/ebean/server/deploy/id/IdBinderEmbedded.java Fri Mar 13 10:40:01 CET 2009@@ -133,6 +133,9 @@ if (i > 0) { sb.append(" AND "); }++ sb.append(embIdProperty.getDbTableAlias());+ sb.append("."); sb.append(props[i].getDbFullName()); sb.append(" = ? "); }
I think I have reproduced the problem.
T0DetailId id = new T0DetailId(3,4); T0Detail detail = Ebean.find(T0Detail.class) .join("master").setId(id).findUnique();
generates sql with no table alias on the embedded id columns... and you get a sql error "Ambiguous column name d1_id ..."
where d1_id = ? AND d2_id = ?
select d.d1_id, d.d2_id, d.detail , m.d1_id, m.name from t0_detail dleft outer join t0_master m on d.m_id = m.d1_id where d1Id = ? AND d2Id = ?
Yes, I understand your fix. I'm pretty happy that it is not a hack... in that the table alias is not set on Embedded beans, so the IF check in BeanProperty is detecting that case... and getting the 'base table alias'.
I'll ponder a bit more but it looks good to me.
Thanks, Rob.
The thing which makes me not that happy is in IdBinderEmbedded.java where I add the table alias, but the javadoc states that getDbFullName() already delivers the full name - with alias.
The other solution I had in mind was to make dbTableAlias non-final and set it in the "second pass" once the table knows its alias.
Yes, I think a better fix is (in BeanPropertyAssocOne) to use:
BeanEmbeddedMeta overrideMeta = BeanEmbeddedMetaFactory.create(owner, deploy, descriptor);embeddedProps = overrideMeta.getProperties();
... it was being used for Embedded beans but not EmbeddedId beans... so I have made the change that it is used for ALL Embedded beans (aka also used for EmbeddedId).
What the BeanEmbeddedMetaFactory does is effectly set the table alias on the properties (returning them via overrideMeta.getProperties();)
That means the getDbFullName() is correct again.
I'm committing up this fix into HEAD along with some other changes (improved error messages and conditionally using the column alias on imported concatinated keys).
Fixed in HEAD.