I've read the documentation, FAQs, and the relevant parts of
Hibernate in Action, many times now. I've been searching the forums, but I haven't found anyone who's described this type of problem. To be fair, finding the right search terms has been a challenge. Every search that sounds relevant brings back a million posts.
Here's a simplified case of my problem.
A user logs in, makes their way through authentication, and the application looks up what they have access to:
Code:
CREATE TABLE User_Access (
User_Access_ID int(11) NOT NULL auto_increment,
Username varchar(64),
Access_To_What varchar(64),
Generic_Name varchar(64),
PRIMARY KEY (User_Access_ID),
UNIQUE KEY SingleSignOn (Username,Access_To_What)
);
Each Username might have access to many things. Each record of User_Access might have the same Generic_Name, or they might all be different.
Code:
CREATE TABLE Generic (
Generic_ID int(11) NOT NULL auto_increment,
Generic_Name varchar(64),
Code varchar(16),
Name varchar(64),
PRIMARY KEY (Generic_ID),
UNIQUE KEY NameAndCode (Generic_Name,Code)
);
Here's an example for Bob:
Username = "Bob", Access_To_What = "Section1", Generic_Name = "DEFAULT"
Username = "Bob", Access_To_What = "Section2", Generic_Name = "DEFAULT"
And the data for DEFAULT:
Generic_Name = "DEFAULT", Code = "codeA", Name = "Red"
Generic_Name = "DEFAULT", Code = "codeB", Name = "Green"
Generic_Name = "DEFAULT", Code = "codeC", Name = "Blue"
I have tried....lots of different ways of trying to get this to map. The problem is there's no nice clean mapping between User_Access_ID and Generic_ID. There's no association table, just Generic_Name.
Mapping for User_Access:
Code:
<hibernate-mapping package="db">
<class name="UserAccess" table="User_Access">
<id
column="User_Access_ID"
name="UserAccessId"
type="integer"
>
<generator class="identity" />
</id>
<property
column="Username"
length="64"
name="Username"
not-null="true"
type="string"
/>
<property
column="Access_To_What"
length="64"
name="Username"
not-null="true"
type="string"
/>
<set name="Generics" table="Generic">
<key column="Generic_Name"/>
<many-to-many class="Generic"/>
</set>
</class>
</hibernate-mapping>
And the mapping for Generic:
Code:
<hibernate-mapping package="db">
<class name="Generic" table="Generic">
<id
column="Generic_ID"
name="GenericId"
type="integer"
>
<generator class="identity" />
</id>
<property
column="Generic_Name"
name="GenericName"
not-null="true"
type="string"
length="64"
/>
<property
column="Code"
name="Code"
not-null="true"
type="string"
length="16"
/>
<property
column="Name"
length="64"
name="Name"
not-null="true"
type="string"
/>
</class>
</hibernate-mapping>
Hibernate version: 2.1.6
MySQL version: 4.0.21
Code between sessionFactory.openSession() and session.close():I haven't included the User mapping or table, or any of the real names for things or all the other crap in these tables. I know I tend to get glassey eyed and move on when I see too much detail. Anyhow, my goal is something like:
Code:
[...]
User u = [hibernate session.find for mapped User table]
Set useraccess_set = u.getUserAccess();
Iterator useraccess_it = useraccess_set.iterator();
while (useraccess_it.hasNext())
{
UserAccess ua = (UserAccess)useraccess_it.next();
Set generics_set = ua.getGenerics();
Iterator generics_it = generics_set.iterator();
out.write("Your Generics:");
while (generics_it.hasNext())
{
Generic g = (Generic)generics_it.next();
out.write(g.getName());
}
}
[...]
Running that inside a test case produces:
Code:
net.sf.hibernate.MappingException: Foreign key (Generic [elt])) must have same number of columns as the referenced primary key (Generic [Generic_Name,elt])
at net.sf.hibernate.mapping.ForeignKey.setReferencedTable(ForeignKey.java:60)
at net.sf.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:691)
at net.sf.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:666)
at net.sf.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:784)
at com.metrixmatrix.test.Main.main(Main.java:47)
Exception in thread "main"
I really apologize if this has been covered a thousand times. I'm really hoping for one of three outcomes:
1) You stink, I do this all the time, here's how.
2) You stink, Hibernate doesn't do this because it's not supposed to.
3) You stink, here let me shoot you and put you out of your misery.