-->
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.  [ 7 posts ] 
Author Message
 Post subject: Trouble with mapping a map
PostPosted: Fri Jan 02, 2009 8:36 pm 
Newbie

Joined: Fri Jan 02, 2009 8:21 pm
Posts: 9
Hi all,

I'm at my wits' end on this one. I'm trying to map a simple map relationship between two entities. The foreign key for the owner is part of the primary key for the owned entity (which is typical).

Using Hibernate 3.2.5

Here are the class excerpts:

Code:
@Entity @Table(name="tip_action") @IdClass(TipActionId.class)
public class TipAction extends AbstractModelObject {
   @Id
   @Column(name="tip_name")
   private String tipName = null;

   @Column(name="action_type")
   @Enumerated(EnumType.STRING)   
   private ActionType actionType = null;
   
   @Column(name="date")
   private Date date = null;
   
   @Id
   @Column(name="person_id", nullable=false, insertable=false, updatable=false)
   private Long personId;
   
   @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER, optional=false)
   @JoinColumn(name="person_id", nullable=false)
   private Person person;
....
}


@Entity @Table(name="person")
public class Person extends AbstractModelObject {
   
   @Id @GeneratedValue(strategy = GenerationType.AUTO)
   private Long id = null;
   
   @Column(name = "customer_id")
   private Integer customerId = null;
   
   @MapKey(name="tipName")
   @OneToMany(fetch=FetchType.EAGER, mappedBy="person", cascade=CascadeType.ALL)
   private Map<String, TipAction> tipActions = new HashMap<String, TipAction>();
...
}

public class TipActionId extends AbstractModelObject implements Serializable {
   @Column(name="person_id")
   Long personId;   
   
   @Column(name="tip_name")
   String tipName;
...
}

This works for retrieval of existing data, but when I try to insert a new Person with a TipAction in the mapping, I get this error:

Code:
/* insert poscore.model.TipAction */ insert into tip_action (action_type, date, person_id, tip_name) values (?, ?, ?, ?)
[dino] WARN [main] JDBCExceptionReporter.logExceptions(77) | SQL Error: 0, SQLState: S1009
[dino] ERROR [main] JDBCExceptionReporter.logExceptions(78) | Parameter index out of range (5 > number of parameters, which is 4).


The query looks correct - that's the right number of fields for the table. But for some reason an extra one is being passed in somewhere.

Moving insertable and updatable = false to the relationship annotation breaks the cascade (I get a "personId can't be null" error)

Any idea what I'm doing wrong?

Thanks in advance,
Sean

P.S. Here's the whole stack trace:
Code:
[dino] ERROR [main] AbstractFlushingEventListener.performExecutions(301) | Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: could not insert: [poscore.model.TipAction]
   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.insert(AbstractEntityPersister.java:2267)
   at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2660)
   at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:56)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
   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.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390)
   at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:420)
   at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
   at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:744)
   at poscore.dao.hibernate.GenericHibernateDAO.persist(GenericHibernateDAO.java:147)
   at poscore.dao.hibernate.PersonHibernateDAO.persist(PersonHibernateDAO.java:13)
   at poscore.dao.hibernate.IntTestPersonHibernateDAO.testCRUD(IntTestPersonHibernateDAO.java:20)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:168)
   at junit.framework.TestCase.runBare(TestCase.java:134)
   at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
   at junit.framework.TestResult$1.protect(TestResult.java:110)
   at junit.framework.TestResult.runProtected(TestResult.java:128)
   at junit.framework.TestResult.run(TestResult.java:113)
   at junit.framework.TestCase.run(TestCase.java:124)
   at junit.framework.TestSuite.runTest(TestSuite.java:232)
   at junit.framework.TestSuite.run(TestSuite.java:227)
   at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
   at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
   at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:138)
   at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:125)
   at org.apache.maven.surefire.Surefire.run(Surefire.java:132)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:308)
   at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:879)
Caused by: java.sql.SQLException: Parameter index out of range (5 > number of parameters, which is 4).
   at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
   at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
   at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
   at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3288)
   at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3272)
   at com.mysql.jdbc.PreparedStatement.setString(PreparedStatement.java:4108)
   at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.setString(NewProxyPreparedStatement.java:963)
   at org.hibernate.type.StringType.set(StringType.java:26)
   at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:136)
   at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:116)
   at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:284)
   at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2008)
   at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2243)
   ... 39 more


Top
 Profile  
 
 Post subject: Side note
PostPosted: Fri Jan 02, 2009 9:05 pm 
Newbie

Joined: Fri Jan 02, 2009 8:21 pm
Posts: 9
By the way, the docs say that the @Column annotations are unnecessary on the composite primary key class. However, if I remove them, the generated query uses the field names instead of the column names, even though the column names are specified in the main class.

For example, if I remove them from the TipActionId class (leaving them in TipAction), here's the query that's generated:

Code:
/* get current state poscore.model.TipAction */ select tipaction_.personId, tipaction_.tipName, tipaction_.action_type as action3_1_, tipaction_.date as date1_, tipaction_.person_id as person5_1_ from tip_action tipaction_ where tipaction_.personId=? and tipaction_.tipName=?


Which naturally gives the error:
Code:
Unknown column 'tipaction_.personId' in 'field list'


Any idea why this is happening?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 05, 2009 11:47 am 
Newbie

Joined: Fri Jan 02, 2009 8:21 pm
Posts: 9
Bump - sorry, but I'm still stuck on this. Anyone have any idea?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 06, 2009 9:48 am 
Beginner
Beginner

Joined: Wed Apr 18, 2007 6:17 pm
Posts: 49
Location: Dominican Republic
Hello did you try to use the person id reference a part of the primary key instead of a Long property as a representation of that reference?

like this

Code:
@Entity @Table(name="tip_action") @IdClass(TipActionId.class)
public class TipAction extends AbstractModelObject {
   @Id
   @Column(name="tip_name")
   private String tipName = null;

   @Column(name="action_type")
   @Enumerated(EnumType.STRING)   
   private ActionType actionType = null;
   
   @Column(name="date")
   private Date date = null;
   
   //Removed
   //@Id
   //@Column(name="person_id", nullable=false, insertable=false,     //updatable=false)
  // private Long personId;
   
   @Id
  // @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER, optional=false)
   //@JoinColumn(name="person_id", nullable=false)
   private Person person;
....
}


You also need to change the id class to reflect the changes proposed above,

Code:
@Embeddable
public class TipActionId implements Serializable
{
  ...

  @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER, optional=false)
   @JoinColumn(name="person_id", nullable=false)
  private Person person;

  ...
}


regards,


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 06, 2009 2:12 pm 
Newbie

Joined: Fri Jan 02, 2009 8:21 pm
Posts: 9
Thanks for the response. I did try that approach. It causes an infinite loop. Apparently a cousin of this known bug in Hibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 06, 2009 3:50 pm 
Beginner
Beginner

Joined: Wed Apr 18, 2007 6:17 pm
Posts: 49
Location: Dominican Republic
I have used this approach with the xml configuration and works flawlessly...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 06, 2009 4:01 pm 
Newbie

Joined: Fri Jan 02, 2009 8:21 pm
Posts: 9
Didn't realize there were actual function differences with the XML configuration. Makes me wonder if I should re-think going with annotations.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.