Complex Hibernate mapping (or not?)

S

Snyke

Once again I'm running against a solid wall of errors, and my head
starts to hurt really badly with this one :)
I have a bidirectional link between two classes

Account <=> User

this being a many-to-many relationship. Until now nothing fancy, but I
have a Class inbetween that manages accessrights called Privilge, this
just has two boolean values (read and write) that tell wether a user
can read or write to the account.

Account <-many-to-one-> Privilege <-one-to-many-> User

basically every Account-User combination has a Privilege. Now the idea
was to have first the mapping of the Privilege Class like this:

<class name="net.snyke.tmm.Privilege" table="privilege">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="read" column="isRead"/>
<property name="write" column="isWrite"/>
</class>

and then let the other classes reference each other over this table:

<set name="accountPrivileges" table="privilege">
<key column="user"/>
<many-to-many column="account" class="net.snyke.tmm.Account"/>
</set>

What I'm trying to say is, why add another two tables to manage the
relationships between Privilege-User and Privilege-Account, when I can
just use the existing table Privilege? Or did I get something wrong?

Regards,
Christian 'Snyke' Decker
http://www.Snyke.net
 
S

Snyke

By now I figured out that what I really want to do is having
one-to-many for user -> privilege, and a many-to-one for
privilege->user, pretty standard case I would assume, however I get
some really weird errors with this mapping file:

<hibernate-mapping>
<class name="net.snyke.tmm.Privilege" table="privilege">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="read" column="isRead"/>
<property name="write" column="isWrite"/>
<many-to-one name="user" class="net.snyke.tmm.UserAccount"
column="user" not-null="true" />
<many-to-one name="account"
class="net.snyke.tmm.FinancialAccount" column="account" not-null="true"
/>
</class>
<class name="net.snyke.tmm.UserAccount" table="users">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="password"/>
<bag name="userPrivileges"
inverse="true"
lazy="false"
cascade="all">
<key column="user_privileges"/>
<one-to-many class="net.snyke.tmm.Privilege"/>
</bag>
</class>
<class name="net.snyke.tmm.FinancialAccount" table="accounts">
<id name="id" column="id">
<generator class="native"/>
</id>
</class>
</hibernate-mapping>

namely this:

17:16:10,052 INFO Configuration:1286 - configuring from resource:
/hibernate.cfg.xml
17:16:10,052 INFO Configuration:1263 - Configuration resource:
/hibernate.cfg.xml
17:16:10,056 INFO Configuration:468 - Reading mappings from resource:
mapping.hbm.xml
17:16:10,144 INFO DriverManagerConnectionProvider:147 - cleaning up
connection pool: jdbc:mysql://localhost/test
17:16:10,153 INFO Mappings:137 - duplicate import:
net.snyke.tmm.Privilege->net.snyke.tmm.Privilege
17:16:10,153 INFO Mappings:137 - duplicate import:
net.snyke.tmm.Privilege->Privilege
17:16:10,154 INFO HbmBinder:265 - Mapping class:
net.snyke.tmm.Privilege -> privilege
%%%% Error Creating HibernateSessionFactory %%%%
org.hibernate.MappingException: Could not read mappings from resource:
mapping.hbm.xml
at org.hibernate.cfg.Configuration.addResource(Configuration.java:484)
at
org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1443)
at
org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1411)
at
org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1392)
at
org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1368)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1288)
at
net.snyke.tmm.persister.HibernateSessionFactory.initSessionFactory(HibernateSessionFactory.java:98)
at
net.snyke.tmm.persister.HibernateSessionFactory.getInstance(HibernateSessionFactory.java:54)
at
net.snyke.tmm.TestUserAccount.testPersistence(TestUserAccount.java:19)
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:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.hibernate.DuplicateMappingException: Duplicate
class/entity mapping net.snyke.tmm.Privilege
at org.hibernate.cfg.Mappings.addClass(Mappings.java:117)
at org.hibernate.cfg.HbmBinder.bindRoot(HbmBinder.java:110)
at org.hibernate.cfg.Configuration.add(Configuration.java:385)
at
org.hibernate.cfg.Configuration.addInputStream(Configuration.java:426)
at org.hibernate.cfg.Configuration.addResource(Configuration.java:481)
... 23 more

Any idea?
 
S

Snyke

Well ok the above should be enough of mapping.hbm.xml since this causes
me the errors.
Anyway here goes the full file:

--------------------------------------
<?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>

<class name="net.snyke.tmm.Privilege" table="privilege">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="read" column="isRead"/>
<property name="write" column="isWrite"/>
<many-to-one name="user" class="net.snyke.tmm.UserAccount"
column="user" not-null="true" />
<many-to-one name="account"
class="net.snyke.tmm.FinancialAccount" column="account" not-null="true"
/>
</class>

<class name="net.snyke.tmm.UserAccount" table="users">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="password"/>
<bag name="userPrivileges"
inverse="true"
lazy="false"
cascade="all">
<key column="user_privileges"/>
<one-to-many class="net.snyke.tmm.Privilege"/>
</bag>
</class>

<class name="net.snyke.tmm.FinancialAccount" table="accounts">
<id name="id" column="id">
<generator class="native"/>
</id>
</class>
</hibernate-mapping>
---------------------

With this mapping I get the aforementioned error:


%%%% Error Creating HibernateSessionFactory %%%%
org.hibernate.MappingException: Could not read mappings from resource:
mapping.hbm.xml
[...]
Caused by: org.hibernate.DuplicateMappingException: Duplicate
class/entity mapping net.snyke.tmm.Privilege
[...]
 
S

Snyke

No idea what you are talking about ^^"
The mapping file is the only actual mapping in all my application, if
that's what you're asking for, I'm not using any XDoclet style mapping
at all.

Regards,
Snyke
 
D

Danno

What is this referring to?

17:16:10,153 INFO Mappings:137 - duplicate import:
net.snyke.tmm.Privilege->net.snyke.tmm.Privilege
17:16:10,153 INFO Mappings:137 - duplicate import:
net.snyke.tmm.Privilege->Privilege
17:16:10,154 INFO HbmBinder:265 - Mapping class:
net.snyke.tmm.Privilege -> privilege


Do you have more than one configuration listing the same thing?
 
S

Snyke

No all I have is a Class Privilege that is mapped to a table directly.
Every Privilege has a reference to a UserAccount and a
FinancialAccount.
Every UserAccount has a List to Privileges (the same goes for
FinancialAccounts but they aren't yet implemented...) and I try to tell
hibernate to take the reference from UserAccount to Privilege as the
mapping in the Privilege class.
Hibernate probably does not understand why I'm using an existing
(mapped class) Privilege to map it to the List in UserAccount.

Any idea?

P.S.:Sorry if the message is not quite understandable, already had some
beers ^^
 
S

Snyke

Hehe, your wish is my command ^^
I think it's best if I put all relevant parts online to show you ^^:

First of all the classes I want to persist:
- http://snyke.net/tmp/UserAccount.java
- http://snyke.net/tmp/FinancialAccount.java
Then the part that initializes Hibernate:
- http://snyke.net/tmp/HibernateSessionFactory.java
And then the hibernate config & mapping files:
- http://snyke.net/tmp/hibernate.cfg.xml
- http://snyke.net/tmp/mapping.hbm.xml

This way we don't get messy posts and I hope you have all information
^^

Thanks for all your help until now :)
Snyke
 
J

JScoobyCed

Snyke said:
Once again I'm running against a solid wall of errors, and my head
starts to hurt really badly with this one :)
I have a bidirectional link between two classes

Account <=> User

this being a many-to-many relationship. Until now nothing fancy, but I
have a Class inbetween that manages accessrights called Privilge, this
just has two boolean values (read and write) that tell wether a user
can read or write to the account.

Account <-many-to-one-> Privilege <-one-to-many-> User

basically every Account-User combination has a Privilege.

Hi. I followed this Thread and triied to give it a check.
I downloaded your code and ran it. I need to create a class BaseVO.java
as you didn't provide it. Here is what I put:

<BaseVO.java>
public class BaseVO {
private int id = -1;
private Privilege[] userPrivileges = null;

public int getId() {
return id;
}

public void setId(int i) {
id = i;
}

public Privilege[] getUserPrivileges() {
return userPrivileges;
}

public void setUserPrivileges(Privilege[] priv) {
userPrivileges = priv;
}
}
</BaseVO.java>

I am not sure the set/get on userPrivileges are in this class or not.
But Hibernate was complaining there was no setter/getter for
userPrivileges in UserAccount. I thought ot put it in BaseVo as it was
not in your original UserAccount.java

Anyway, after creating the DB in mysql, the only output I have is:

classic factory

I don't have any error message. So I guess you might have a different DB
than me. Here is my DB script:

<db_mysql>
CREATE TABLE accounts (
id int(11) NOT NULL,
`name` varchar(32) NOT NULL
);

CREATE TABLE privilege (
id int(11) NOT NULL auto_increment,
isread tinyint(4) NOT NULL,
iswrite tinyint(4) NOT NULL,
`user` int(11) NOT NULL,
account int(11) NOT NULL,
PRIMARY KEY (id)
);

CREATE TABLE users (
id int(11) NOT NULL auto_increment,
`name` varchar(32) NOT NULL,
`password` varchar(32) NOT NULL,
user_privileges int(11) NOT NULL,
PRIMARY KEY (id)
);

</db_mysql>

Note that MySQl (and many DBMS) have 'user', 'password' and 'name'
reserved (so MySQl encloses them with backquotes). Maybe that's what is
perturbing Hibernate. I am using hibernate 3.
 
S

Snyke

Finally!

I got Hibernate to work correctly, but I really can't tell what I
changed. After being very close to giving up on hibernate (yes, I
nearly coded all persistence directly into the objects...) I decided,
that I'd give it a last try, with a completely new Project and going
step by step through it, and it worked just perfect.

Here's a link to this sample application, hope it may help others ^^
http://www.snyke.net/tmp/HibernateTest.tar.bz2

Thanks for all contributors,
Christian 'Snyke' Decker
http://www.Snyke.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top