-->
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: hbm.xml mappings
PostPosted: Tue Mar 28, 2006 1:29 pm 
Beginner
Beginner

Joined: Thu Mar 09, 2006 1:45 pm
Posts: 26
I had to change my primary key from a single id, companyId to multiple ids, ( companyId, locationId ). How do I set the foreign key for the child. Before I just did:


<set name="employees" cascade="save-update" inverse="true" lazy="false">
<key column="companyId"/>
<one-to-many class="org.hibernate.testing.Employee"/>
</set>


Now that I have 2 primary keys, how do I pick up the locationId?





<?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
package="org.hibernate.testing.config">

<class name="org.hibernate.testing.Company" table="Company">
<composite-id>
<key-property name="companyId" type="long" column="companyId"/>
<key-property name="locationId" type="long" column="locationId"/>
</composite-id>
<property name="name" column="companyName" type="string"
length="15" not-null="true"/>
<property name="address" column="address" type="string"
length="25" not-null="true"/>

<set name="employees" cascade="save-update" inverse="true" lazy="false">
<key column="companyId"/>
<one-to-many class="org.hibernate.testing.Employee"/>
</set>
</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 28, 2006 2:01 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
instead of <key column="companyId"/>
put:
<key>
<column name="companyId"/>
<column name="locationId"/>
</key>

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 28, 2006 4:56 pm 
Beginner
Beginner

Joined: Thu Mar 09, 2006 1:45 pm
Posts: 26
I am getting this exception when running now:

Exception in thread "main" org.hibernate.MappingException: Repeated column in mapping for entity: org.hibernate.testing.Employee column: locationId (should be mapped with insert="false" update="false")

at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:504)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:526)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:544)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:335)
at org.hibernate.mapping.RootClass.validate(RootClass.java:188)
at org.hibernate.cfg.Configuration.validate(Configuration.java:839)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1000)
at org.hibernate.testing.Main.main(Main.java:511)

My data is pretty simple. I have a company with these attributes:

private String name = null;
private String address = null;
private long companyId = 0;
private long locationId = 0;
private Set employees = null;

Employees have these attributes:

private String lastName = null;
private double salary = 0;
private String firstName = null;
private int ssn = 0;
private long locationId = 0;
private Company company = null;

The primary keys are companyId and locationId for Company and ssn, firstName and locationId for employee. The foreign key for Employee is locationId and companyId. I know this is a bad schema, but it mirrors other data I am working on, so I can have the same ssn and firstname at different locationIds.

ssn Fname locId
1 joe 1
1 joe 2 This is ok

How do I get my hbm.xml mappings to allow this so I don't get the above excpetion? I need it to allow the locationid to be the foreignKey and primary key in my employee table.

Here are my xml config files


// this is the company mapping

<?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
package="org.hibernate.testing.config">

<class name="org.hibernate.testing.Company" table="Company">
<composite-id>
<key-property name="companyId" type="long" column="companyId"/>
<key-property name="locationId" type="long" column="locationId"/>
</composite-id>
<property name="name" column="companyName" type="string"
length="15" not-null="true"/>
<property name="address" column="address" type="string"
length="25" not-null="true"/>

<set name="employees" cascade="save-update" inverse="true" lazy="false">
<key>
<column name="companyId"/>
<column name="locationId"/>
</key>
<one-to-many class="org.hibernate.testing.Employee"/>
</set>

</class>
</hibernate-mapping>

// this is the employee mapping

<?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
package="org.hibernate.testing">
<class name="Employee" table="Employee">
<composite-id>
<key-property name="ssn" type="integer" column="ssn"/>
<key-property name="firstName" column="firstName" type="string" length="15"/>
<key-property name="locationId" column="locationId" type="long" />
</composite-id>

<property name="lastName" column="lastName" type="string"
length="15" not-null="true"/>
<property name="salary" column="salary" type="double" not-null="true"/>
<many-to-one name="company" class="Company" not-null="true" >
<column name="companyId"/>
<column name="locationId" />
</many-to-one>

</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 28, 2006 5:36 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
Here is a sample (it has the id and class in the composite-id tags, that I noticed is diff from yours)...

The "class" is a class the defines the PK of an Order.

Order (1) to (M) LineItem

LineItem.hbm.xml:
Code:
<class name="LineItem">

   <composite-id name="id"
      class="LineItem$Id">
      <key-property name="customerId" length="10"/>
      <key-property name="orderNumber"/>
      <key-property name="productId" length="10"/>
   </composite-id>

   <property name="quantity"/>

   <many-to-one name="order"
      insert="false"
      update="false"
      not-null="true">
      <column name="customerId"/>
      <column name="orderNumber"/>
   </many-to-one>

   <many-to-one name="product"
      insert="false"
      update="false"
      not-null="true"
      column="productId"/>

</class>


Order.hbm.xml:

Code:
<class name="Order" table="CustomerOrder">
   <synchronize table="LineItem"/>
   <synchronize table="Product"/>

   <composite-id name="id"
      class="Order$Id">
      <key-property name="customerId" length="10"/>
      <key-property name="orderNumber"/>
   </composite-id>

   <property name="orderDate"
      type="calendar_date"
      not-null="true"/>

   <property name="total"
      formula="( select sum(li.quantity*p.price) from LineItem li, Product p where li.productId = p.productId and li.customerId = customerId and li.orderNumber = orderNumber )"/>

   <many-to-one name="customer"
      column="customerId"
      insert="false"
      update="false"
      not-null="true"/>

   <bag name="lineItems"
      fetch="join"
      lazy="false"
      inverse="true"
      cascade="save-update">
      <key>
         <column name="customerId"/>
         <column name="orderNumber"/>
      </key>
      <one-to-many class="LineItem"/>
   </bag>

</class>


This is straight from the <hib3>/test/cid directory...

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 28, 2006 7:20 pm 
Beginner
Beginner

Joined: Thu Mar 09, 2006 1:45 pm
Posts: 26
I am still running into problems. I do not get the exception anymore, but I also do not have the companyId inserted into the employee db table. I need this as the foreign key back to the company data. If I try and remove the companyid key from the employee.hbm.xml one-to-many mapping, since I say update/save ="false", I get this exception:

Exception in thread "main" org.hibernate.MappingException: Foreign key (FK4AFD4ACE5C5A35E9:Employee [locationId])) must have same number of columns as the referenced primary key (Company [companyId,locationId])
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:86)
at org.hibernate.mapping.ForeignKey.setReferencedTable(ForeignKey.java:51)
at org.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:976)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:921)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:999)
at org.hibernate.testing.Main.main(Main.java:517)


I need the companyId to be inserted into the database. I was just doing this code and it was working fine:

for( int x =0; x <3:x++ )
{
Company company = new Company();
company.setCompanyId(x);
company.setName("compName"+x);
company.setAddress( x + " Main St");
company.setLocationId(x);

Set empSet = new HashSet();
for( int y = 0; y < 2 ; y++)
{

Employee employee = new Employee();
employee.setSsn(y+1);
employee.setFirstName("fName" + y);
employee.setLastName("lName" + counter);
employee.setSalary(counter*counter+5000);
employee.setLocationId(x);
employee.setCompanyId(company.getCompanyId() );

employee.setCompany(company);
empSet.add(employee);

}
company.setEmployees(empSet);
s.save(company);
tx.commit();
}


The s.save(company) line would cascade saving the company and all associated employees, but now the companyId is not saved.

Company PK = companyId, locationId
Employee PK = locationId, ssn, firstName
Employee FK = locationId, companyId

Not sure what to do now


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 28, 2006 7:29 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
you shouldn't be managing ID in your object for the relationship part -- in otherwords don't set employee.companyid, but rather employee.company and let the company object itself contain the correct keys.

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 28, 2006 7:37 pm 
Beginner
Beginner

Joined: Thu Mar 09, 2006 1:45 pm
Posts: 26
I got rid of the

employee.setCompanyId(company.getCompanyId() ); line but it still did not save. I believe it is because of my previous problem in the employee.hbm.xml file. Since the companyId is used as the foreign key with locationId and locationId is part of the primary key, I have to set save="false" and update="false" in one-to-many mappings. This prevents the companyId from saving.


<class name="org.hibernate.testing.Company" table="Company">

<composite-id>
<key-property name="companyId" type="long" column="companyId"/>
<key-property name="locationId" type="long" column="locationId"/>
</composite-id>
<property name="name" column="companyName" type="string"
length="15" not-null="true"/>
<property name="address" column="address" type="string"
length="25" not-null="true"/>


<set name="employees" cascade="save-update" inverse="true" lazy="false" fetch="join">
<key>
<column name="companyId"/>
<column name="locationId"/>
</key>
<one-to-many class="org.hibernate.testing.Employee" />
</set>
</class>


package="org.hibernate.testing">
<class name="Employee" table="Employee">
<composite-id>
<key-property name="ssn" type="integer" column="ssn"/>
<key-property name="firstName" column="firstName" type="string" length="15"/>
<key-property name="locationId" column="locationId" type="long" />
</composite-id>

<property name="lastName" column="lastName" type="string"
length="15" not-null="true"/>
<property name="salary" column="salary" type="double" not-null="true"/>
<many-to-one name="company" class="Company" not-null="true" insert="false" update="false" >
<column name="companyId"/>
<column name=
"locationId" />
</many-to-one>
</class>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 28, 2006 8:16 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
don't worry about that for now - go with what should work first...

Get rid of all occasions where you are using the ID's directly and make sure it is completely related by objects -- ie:

Code:
employee.setLocationId(x);


The only place you're dealing with IDs and FKs are with each entity bjects as you setup it's own ID, and the FK.

Did you notice how the sample has a "class" defined that represents the ID's on each of the entities?

It should look like similar to this when you're done
Off the top of my head without testing for typos, this should work.


Code:
Company
{
   CompanyPK coPK=null;
   String name="";
    Set emps=null;
  getters/settters for pk and name and set.
}


Code:
CompanyPK
{
    Long companyId=null;
    Long locationId=null;
    //getters/setters, hashCode and equals
}


Code:
Employee
{
    EmployeePK empPK=null;
    String empno="";
    Company co=null;
   //getters and setters for empPK and empno, and co
}


Code:
EmployeePK
{
    Long empId=null;
    Long companyId=null;
    Long locationId=null;
    //getters/setters, hashCode and equals
}



Then your mapping would be:

Code:
<class name="Company">

   <composite-id name="coPK"
      class="CompanyPK">
      <key-property name="companyId"/>
      <key-property name="locationId"/>
   </composite-id>

   <property name="name">

   <set name="emps"
      fetch="join"
      lazy="false"
      inverse="true"
      cascade="save-update">
      <key>
         <column name="companyId"/>
         <column name="locationId"/>
      </key>
      <one-to-many class="Employee"/>
   </set>

</class>



Code:
<class name="Employee">
   <composite-id name="empPK"
      class="EmployeePK">
      <key-property name="companyId" />
      <key-property name="locationId"/>
      <key-property name="empId"/>
   </composite-id>

   <property name="empno"/>

   <many-to-one name="co">
      <column name="companyId"/>
      <column name="locationId"/>
   </many-to-one>

</class>



Then in your java code do something like:

Code:
Company co=new Company();
CompanyPK coPK=new CompanyPK ();
coPK.setLocationId(234);
coPK.setCompanyId(444);
co.setCoPK(coPK):
co.setName("bbb");
co.setEmps(new HashSet());

Employee emp1=new Employee();
EmployeePK empPK=new EmployeePK();
empPK.setLocationId(234);
empPK.setCompanyId(444);
empPK.setEmpId(1);
emp1.setEmpPK(empPK);
emp1.setCo(co);

co.getEmps().add(emp1);

tx=sees.beginTransaction();
sess.saveOrUpdate(co);
tx.commit();


//both company and it's one emp are saved to database at this point.

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 29, 2006 12:32 pm 
Beginner
Beginner

Joined: Thu Mar 09, 2006 1:45 pm
Posts: 26
Still getting the exception:

Exception in thread "main" org.hibernate.MappingException: Repeated column in mapping for entity: org.hibernate.testing.Employee column: locationId (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:504)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:526)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:544)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:335)
at org.hibernate.mapping.RootClass.validate(RootClass.java:188)
at org.hibernate.cfg.Configuration.validate(Configuration.java:839)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1000)
at org.hibernate.testing.Main.main(Main.java:542)


I created a primary key for company that takes companyId and locationId and for the employeePk it is firstname, locationid and ssn. The foreign keys are companyId and locationId. Again, if I do the insert="false" and update="false" like the exception says, the companyId is not inserted in the database.

Here are my mappings


<hibernate-mapping
package="org.hibernate.testing">

<class name="org.hibernate.testing.Employee">
<composite-id name="employeePk" class="org.hibernate.testing.EmployeePK">
<key-property name="ssn" type="integer" column="ssn"/>
<key-property name="firstName" column="firstName" type="string" length="15"/>
<key-property name="locationId" column="locationId" type="long"/>
</composite-id>

<property name="lastName" column="lastName" type="string"
length="15" not-null="true"/>
<property name="salary" column="salary" type="double" not-null="true"/>

<many-to-one name="company">
<column name="companyId"/>
<column name="locationId" />
</many-to-one>
</class>
</hibernate-mapping>


<hibernate-mapping
package="org.hibernate.testing.config">

<class name="org.hibernate.testing.Company">
<composite-id name="companyPK" class="org.hibernate.testing.CompanyPK">
<key-property name="companyId" type="long" column="companyId"/>
<key-property name="locationId" type="long" column="locationId"/>
</composite-id>
<property name="name" column="companyName" type="string"
length="15" not-null="true"/>
<property name="address" column="address" type="string"
length="25" not-null="true"/>

<set name="employees"
fetch="join"
lazy="false"
inverse="true"
cascade="save-update">
<key>
<column name="companyId"/>
<column name="locationId"/>
</key>
<one-to-many class="org.hibernate.testing.Employee" />
</set>

<set name="products"
fetch="join"
lazy="false"
inverse="true"
cascade="save-update">
<key>
<column name="companyId"/>
<column name="locationId"/>
</key>
<one-to-many class="org.hibernate.testing.Product"/>
</set>

</class>
</hibernate-mapping>


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.