-->
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.  [ 9 posts ] 
Author Message
 Post subject: SQLGrammarException: could not initialize a collection
PostPosted: Thu Jan 05, 2006 2:11 pm 
Newbie

Joined: Thu Jan 05, 2006 1:56 pm
Posts: 7
Hibernate version: 3.1

Mapping documents:

<hibernate-mapping default-lazy="false">
<class name="iSoft.Entity.Software" table="ms_software">

<id name="softwareId">
<generator class="guid"/>
</id>

<property name="softwareName" />
<set lazy="false" inverse="true" name="purchases" table="tr_purchase">
<key>
<column name="softwareId" />
</key>
<many-to-many class="iSoft.Entity.User" />
</set>

</class>


<class name="iSoft.Entity.Purchase" table="tr_purchase">
<composite-id>
<key-property name="softwareId" />
<key-property name="username" />
</composite-id>
<property name="purchaseDate" column="purchaseDate"/>
</class>

<class name="iSoft.Entity.User" table="ms_user">

<id name="username">
<generator class="assigned"/>
</id>

<property name="userFirstName" />
<property name="userLastName" /> </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
Session session = HibernateHelper.getSession();
// ini utk bikin listnya =D session.createCriteria(Software.class);
Iterator iter = session.createCriteria(Software.class).list().iterator();
ArrayList list = new ArrayList();

Full stack trace of any exception that occurs:
root cause

org.hibernate.exception.SQLGrammarException: could not initialize a collection: [iSoft.Entity.Software.purchases#de9c7d35-cccf-1028-8]
org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:70)
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
org.hibernate.loader.Loader.loadCollection(Loader.java:1441)
org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:99)
org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:488)
org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1430)
org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:280)
org.hibernate.engine.PersistenceContext.initializeNonLazyCollections(PersistenceContext.java:796)
org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:223)
org.hibernate.loader.Loader.doList(Loader.java:1593)
org.hibernate.loader.Loader.list(Loader.java:1577)
org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:111)
org.hibernate.impl.SessionImpl.list(SessionImpl.java:1322)
org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:300)
iSoft.Web.Tags.ProgrammingLanguageList.doTag(ProgrammingLanguageList.java:47)
org.apache.jsp.index_jsp._jspx_meth_iSoft_ProgrammingLanguageList_0(index_jsp.java:235)
org.apache.jsp.index_jsp._jspService(index_jsp.java:102)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:99)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:325)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:245)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)



Name and version of the database you are using:
MySQL 4.1

The generated SQL (show_sql=true):
Hibernate: select this_.softwareId as softwareId0_, this_.softwareName as software2_3_0_, this_.softwareImage as software3_3_0_, this_.softwarePrice as software4_3_0_, this_.softwareDescription as software5_3_0_, this_.programmingLanguage as programm6_3_0_ from ms_software this_
Hibernate: select purchases0_.softwareId as softwareId1_, purchases0_.elt as elt1_, user1_.username as username0_, user1_.userFirstName as userFirs2_0_0_, user1_.userLastName as userLast3_0_0_, user1_.userDOB as userDOB0_0_, user1_.isAdmin as isAdmin0_0_, user1_.userEmail as userEmail0_0_, user1_.userPhone as userPhone0_0_, user1_.userAddress as userAddr8_0_0_, user1_.userCountry as userCoun9_0_0_, user1_.ccType as ccType0_0_, user1_.ccNumber as ccNumber0_0_, user1_.hashCode as hashCode0_0_, user1_.ccExpireDate as ccExpir13_0_0_, user1_.secretQuestion as secretQ14_0_0_, user1_.secretAnswer as secretA15_0_0_ from tr_purchase purchases0_ inner join ms_user user1_ on purchases0_.elt=user1_.username where purchases0_.softwareId=?

public class Software {

private String softwareId;
private String softwareName;
private Set purchases = new HashSet();

public Set getPurchases()
{
return purchases;
}

public void setPurchases(Set newPurchases)
{
purchases = newPurchases;
}
}

Database schema:
ms_user {username PK, firstname, lastname}
ms_software {softwareId PK, softwareName}
tr_purchase {username PK FK, softwareId PK FK, purchaseDate}

I tried to get list of purchase, from tr_purchase, by accessing purchase property from Software. But there's an exception "could not initialize collection purchase". Anyone knows why is this happening?

Thanks in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 7:31 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
It looks like you're trying to set up a many-to-many from Software to User, via the join table Purchase. But you have no association between Purchase and User, or between Software and Purchase. You don't want a many-to-many with a join table, because then you don't get to model the Purchase class (see ref docs, chapter "Association Mappings", section "many-to-many"). You want a many-to-many collection mapping from Software to Purchase, and a normal one-to-many or many-to-one mapping from Purchase to User.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 9:06 pm 
Newbie

Joined: Thu Jan 05, 2006 1:56 pm
Posts: 7
thx for your quick reply, tenwit.
But I don't quite understand, what do you mean with "It looks like you're trying to set up a many-to-many from Software to User, via the join table Purchase. But you have no association between Purchase and User, or between Software and Purchase."? I thought I used foreign keys on them.

Anyway, I have modified my mapping file a little bit. It worked, but still some problem. I can now access list of purchase from software object, but somehow the "purchaseDate" property seemed to be untouched. Because when I tried to print the value, it turned up it was null. I find this weird because I've entered the value on the database.

Here's my mapping file and source code of purchase class.

<class name="iSoft.Entity.Software" table="ms_software">

<id name="softwareId">
<generator class="guid"/>
</id>

<property name="softwareName" />
<set lazy="false" name="purchases" table="tr_purchase">
<key>
<column name="softwareId" />
</key>
<composite-element class="iSoft.Entity.Purchase">
<property name="username" />
<property name="purchaseDate" />
</composite-element>
</set>
</class>

public class Purchase {

private String username;
private String softwareId;
private Date purchaseDate;
private User user;
private Software software;

public User getUser()
{
return user;
}

public Software getSoftware()
{
return software;
}

public void setSoftware(Software s)
{
software = s;
}

public void setUser(User u)
{
user = u;
}
/** Creates a new instance of Purchase */
public Purchase() {
username = "";
softwareId = "";
purchaseDate = new Date();
}

public String getUsername()
{
return username;
}
public void setUsername(String newUsername)
{
username = newUsername;
}

public String getSoftwareId()
{
return softwareId;
}
public void setsoftwareId(String newSoftwareId)
{
softwareId = newSoftwareId;
}

public Date getPurchaseDate()
{
return purchaseDate;
}
public void setPurchaseDate(Date newPurchaseDate)
{
purchaseDate = newPurchaseDate;
}

}


Anyone knows what's wrong with this?
Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 9:29 pm 
Newbie

Joined: Thu Jan 05, 2006 1:56 pm
Posts: 7
Sorry, it turned out that the value wasn't null. That was some cache problem.

Okay, I've got the mapping part worked, but what I got from the mapping is the "value" of the join table. Can I got the value of the reference of the value of the join table?

For instance, now I have Software object. I can access list of Purchase from Software object. However, this Purchase object contains only the value of the join table (softwareId, username, and purchaseDate). Is it possible for me to access User object from this Purchase object?
So instead of having value of softwareId and username in Purchase class, I would like to have value of Software and User class.

Anyone can help me on this?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 9:56 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
If you're getting values instead of objects, it's because you're using <property> tags instead of <many-to-one> or <one-to-many> (or whatever) tags. You haven't included your full mapping files; if you can't get your references working, post the files here and I'll point out where you're going wrong.

BTW please make use of the code tag when posting here, when appropriate. Reading your posts is really hard work. And don't forget to vote if the response helps.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 10:15 pm 
Newbie

Joined: Thu Jan 05, 2006 1:56 pm
Posts: 7
Here's my full mapping file

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-lazy="false">
   <class name="iSoft.Entity.Software" table="ms_software">
      
      <id name="softwareId">
         <generator class="guid"/>
      </id>

      <property name="softwareName" />
                <property name="softwareImage" />
                <property name="softwarePrice" />
                <property name="softwareDescription" />
                <property name="programmingLanguage" />
               
                <set lazy="false" name="categories" table="tr_has">
                    <key column="softwareId" />
                    <many-to-many class="iSoft.Entity.Category" column="categoryId" />
                </set>
               
                <set lazy="false" name="purchases" table="tr_purchase">
                    <key>
                        <column name="softwareId" />
                    </key>
                    <composite-element class="iSoft.Entity.Purchase">
                        <property name="username" />
                        <property name="purchaseDate" />
                    </composite-element>
                </set>
               
   </class>
   
   <class name="iSoft.Entity.Purchase" table="tr_purchase">
      <composite-id>
                    <key-property name="softwareId" />
                    <key-property name="username" />
                </composite-id>
                <many-to-one class="iSoft.Entity.Software" name="software" column="softwareId" insert="false" update="false" />
                <property name="purchaseDate" column="purchaseDate"/>
   </class>      

   <class name="iSoft.Entity.User" table="ms_user">
      
      <id name="username">
         <generator class="assigned"/>
      </id>
            
      <property name="userFirstName" />
                <property name="userLastName" />
                <property name="userDOB" />
                <property name="admin" column="isAdmin" />
                <property name="userEmail" />
                <property name="userPhone" />
                <property name="userAddress" />
                <property name="userCountry" />
                <property name="ccType" />
                <property name="ccNumber" />
                <property name="hashCode" />
                <property name="ccExpireDate" />
                <property name="secretQuestion" />
                <property name="secretAnswer" />
   </class>
</hibernate-mapping>


I still can't' figure it out how to do many-to-many.
I tried to use <many-to-many class="iSoft.Entity.User" />, but there's error: org.hibernate.exception.SQLGrammarException: could not initialize a collection: [iSoft.Entity.Software.purchases#2aa4d792-ccbe-1028-8]

I also tried to use <many-to-many class="iSoft.Entity.Purchase" />, but there's error: org.hibernate.MappingException: Foreign key (FKADA395A257788B9E:tr_purchase [elt])) must have same number of columns as the referenced primary key (tr_purchase [softwareId,elt])

And btw, what is this elt?
Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 11:57 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
elt means element. If you have a primary key [softwareId, username], all foreign keys referring to it must be exactly the same.

In your Software mapping, you're describing a Purchase as a composite element. Then you define a Purchase mapping. Have you read the reference documentation? You're not even close to the examples in there. You never want to define a class and a composite element describing the same thing.

I'm still not exactly sure of the relationships that you want, but here's a guess. One Software instance can have many Purchases, so you want a <set> containing a <one-to-many>. The <key> in a <set> describes the columns in the contained table that are the foreign key back to the containing table. So in Software, you want something like

Code:
<set table="tr_purchase" name="purchases" inverse="true">
  <key column="softwareId"/>
  <one-to-many class="Purchase">
</set>


You want a bidirectional mapping. So in Purchase, you need a many-to-one back to Software. Because you can't use a column twice in the same mapping, and softwareId is already defined as part of the key, you have to use a formula for the mapping. So in Purchase, put something like this:

Code:
<many-to-one name="software" formula="softwareId" class="Software"/>


A Purchase refers to one User, suggesting a one-to-one mapping, but in hibernate, one-to-one means that both tables use the same primary key. So what you want is a unique one-to-many. In Purchase, put something like this:

Code:
<one-to-many name="user" class="User" unique="true"/>


And apparently you don't want a bidirectional mapping in this case, so User doesn't need any mapping to Purchase.

Give all that a go, and if it doesn't help, describe in a bit more detail how you want the relationships to go.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 06, 2006 1:14 am 
Newbie

Joined: Thu Jan 05, 2006 1:56 pm
Posts: 7
I've followed your suggestion exactly, however there's still some error.
Can you help me one more time :)

Code:
java.lang.ClassCastException: iSoft.Entity.Purchase
   org.hibernate.loader.Loader.getKeyFromResultSet(Loader.java:759)
   org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:292)
   org.hibernate.loader.Loader.doQuery(Loader.java:412)
   org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
   org.hibernate.loader.Loader.loadCollection(Loader.java:1434)
   org.hibernate.loader.collection.OneToManyLoader.initialize(OneToManyLoader.java:111)
   org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:488)
   org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
   org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1430)
   org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:280)
   org.hibernate.engine.PersistenceContext.initializeNonLazyCollections(PersistenceContext.java:796)
   org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:223)
   org.hibernate.loader.Loader.doList(Loader.java:1593)
   org.hibernate.loader.Loader.list(Loader.java:1577)
   org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:111)
   org.hibernate.impl.SessionImpl.list(SessionImpl.java:1322)
   org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:300)
   iSoft.Web.Tags.ProgrammingLanguageList.doTag(ProgrammingLanguageList.java:47)
   org.apache.jsp.index_jsp._jspx_meth_iSoft_ProgrammingLanguageList_0(index_jsp.java:235)
   org.apache.jsp.index_jsp._jspService(index_jsp.java:102)
   org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:99)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
   org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:325)
   org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
   org.apache.jasper.servlet.JspServlet.service(JspServlet.java:245)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
   org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)


Thanks.
Best Regards


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 08, 2006 4:33 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
What does your mapping file look like now? The exception suggests that you've got a <map> in there somewhere; I can't think of any other reason to use a Purchase as a key for anything.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 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.