Problem is at the bottom...
Hibernate version:
3.2.1.GA (HAN&HEM as well)
Mapping documents:
I have 3 entities that I'm trying to deal with.
Activity has a Collection of Series. Series itself is a Single Table Inheritance Model based on the SeriesType.
So we'd like to use a map in the activity to be able to pluck a series out based on it's type.
Activity has a OneToMany relation to Series, based on a join table 'activity_has_series'.
Code:
@Entity
@Table(name = "activity")
public class Activity extends Value<ActivityPk> {
private static final long serialVersionUID = -4001894465214129237L;
@Id
@GeneratedValue
@Column(name = "activity_pk")
private Long pk;
@Column
private String name;
// @org.hibernate.annotations.MapKey(columns = { @Column(name = "series_type_pk") })
@MapKeyManyToMany(joinColumns = @JoinColumn(name = "series_type_pk", updatable = false))
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "activity")
private Map<SeriesType, Series> series;
@ManyToOne
@JoinColumn(name = "user_profile_pk")
private UserProfile userProfile;
public Activity() {
// TODO: will this maintain order for the list of elements for each key?
// series = new HashMap<Long, Series>();
series = new HashMap<SeriesType, Series>();
}
and some getters/setters
}
Code:
@Entity
@Table(name = "series_type")
public class SeriesType extends Value<SeriesTypePk> {
private static final long serialVersionUID = 3053728191682092076L;
@Id
@GeneratedValue
@Column(name = "series_type_pk")
private Long pk;
@Column(name = "series_type")
private String name;
public SeriesType() {
super();
}
and some getters/setters
}
Code:
@Entity
@Table(name = "series")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "series_type_pk", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Series extends Value<SeriesPk> {
@Id
@GeneratedValue
@Column(name = "series_pk")
private Long pk;
@Column
private String name;
@ManyToOne
@JoinColumn(name = "user_profile_pk")
private UserProfile userProfile;
@ManyToOne
@JoinTable(name = "activity_has_series", joinColumns = @JoinColumn(name = "series_pk"), inverseJoinColumns = @JoinColumn(name = "activity_pk"))
private Activity activity;
@ManyToOne
@JoinColumn(name = "series_type_pk", insertable = false, updatable = false)
private SeriesType seriesType;
@OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.REMOVE }, mappedBy = "series")
@IndexColumn(name = "sample_pk", base = 1)
protected List<Sample> samples;
public Series() {
this.samples = new ArrayList<Sample>();
}
}
Code between sessionFactory.openSession() and session.close():
Activity activity = dao.findById(new ActivityPk(2L)); //in a unit test
Full stack trace of any exception that occurs:
WARN 21-02 09:01:51,781 (Log4JLogger.java:warn:104) -SQL Error: 1054, SQLState: 42S22
ERROR 21-02 09:01:51,781 (Log4JLogger.java:error:114) -Unknown column 'series1_.series2_.series_type_pk' in 'field list'
INFO 21-02 09:01:51,781 (Log4JLogger.java:info:99) -Error performing load command
org.hibernate.exception.SQLGrammarException: could not load an entity: [com.garmin.mb.activity.Activity#2]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1799)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2821)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:370)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:351)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:122)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:178)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:86)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:871)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:801)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:155)
at org.jboss.ejb3.entity.TransactionScopedEntityManager.find(TransactionScopedEntityManager.java:164)
at com.garmin.mb.dao.GenericDaoBean.findById(GenericDaoBean.java:80)
at com.garmin.mb.activity.dao.ejb3.ActivityDaoBean.findById(ActivityDaoBean.java:27)
at com.garmin.mb.activity.dao.ejb3.ActivityDaoBean.findById(ActivityDaoBean.java:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.jboss.aop.joinpoint.MethodInvocation.invokeTarget(MethodInvocation.java:121)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:110)
at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:197)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:102)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:211)
at org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalProxy.java:79)
at $Proxy34.findById(Unknown Source)
at com.garmin.mb.activity.dao.ejb3.ActivityDaoUnitTest.testRetrieveActivity(ActivityDaoUnitTest.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:75)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:36)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'series1_.series2_.series_type_pk' in 'field list'
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3176)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1153)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1266)
at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:236)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1669)
at org.hibernate.loader.Loader.doQuery(Loader.java:662)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
... 67 more
Name and version of the database you are using:
mysql 5.0.30
The generated SQL (show_sql=true):
[code]
select
activity0_.activity_pk as activity1_30_6_,
activity0_.name as name30_6_,
activity0_.user_profile_pk as user3_30_6_,
series1_.activity_pk as activity2_8_,
series2_.series_pk as series1_8_,
series1_.series_type_pk as series3_8_, //change to series2_.series_type_pk as series3_8_,
series2_.series_pk as series2_36_0_,
series2_.name as name36_0_,
series2_.user_profile_pk as user4_36_0_,
series2_.series_type_pk as series1_36_0_,
series2_1_.activity_pk as activity2_37_0_,
userprofil3_.user_profile_pk as user1_39_1_,
userprofil3_.username as username39_1_,
seriestype4_.series_type_pk as series1_38_2_,
seriestype4_.series_type as series2_38_2_,
samples5_.series_pk as series1_9_,
samples5_.sample_pk as sample2_9_,
samples5_.series_pk as series1_35_3_,
samples5_.sample_pk as sample2_35_3_,
measuremen6_.series_pk as series2_10_,
measuremen6_.sample_pk as sample3_10_,
measuremen6_.sample_value_pk as sample4_10_,
measuremen6_.series_pk as series2_31_4_,
measuremen6_.sample_pk as sample3_31_4_,
measuremen6_.sample_value_pk as sample4_31_4_,
measuremen6_.float_c as float5_31_4_,
measuremen6_.float_a as float6_31_4_,
measuremen6_.float_b as float7_31_4_,
measuremen6_.datetime_a as datetime8_31_4_,
measuremen6_.sample_value_type_pk as sample1_31_4_,
userprofil7_.user_profile_pk as user1_39_5_,
userprofil7_.username as username39_5_
from
Activity activity0_
left outer join
activity_has_series series1_
on activity0_.activity_pk=series1_.activity_pk
left outer join
series series2_
on series1_.series_pk=series2_.series_pk
left outer join
activity_has_series series2_1_
on series2_.series_pk=series2_1_.series_pk
left outer join
user_profile userprofil3_
on series2_.user_profile_pk=userprofil3_.user_profile_pk
left outer join
series_type seriestype4_
on series2_.series_type_pk=seriestype4_.series_type_pk
left outer join
sample samples5_
on series2_.series_pk=samples5_.series_pk
left outer join
sample_value measuremen6_
on samples5_.series_pk=measuremen6_.series_pk
and samples5_.sample_pk=measuremen6_.sample_pk
left outer join
user_profile userprofil7_
on activity0_.user_profile_pk=userprofil7_.user_profile_pk
where
activity0_.activity_pk=?
[code]
So, the interesting thing is the sql that is generated. It's invalid. If I make the change as commented, then it becomes valid sql. Obviously that's great, but how do I get Hibernate to do that at run-time?
I think I've tried just about every possibility, but was wondering if maybe somebody sees something I don't. I have maps working elsewhere, but this is the first time we've used it with Inheritance(series) and had the key as an entity.
Thanks,
Jason