Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I map "insert='false' update='false'" on a composite-id key-property which is also used in a one-to-many FK?

I am working on a legacy code base with an existing DB schema. The existing code uses SQL and PL/SQL to execute queries on the DB. We have been tasked with making a small part of the project database-engine agnostic (at first, change everything eventually). We have chosen to use Hibernate 3.3.2.GA and "*.hbm.xml" mapping files (as opposed to annotations). Unfortunately, it is not feasible to change the existing schema because we cannot regress any legacy features.

The problem I am encountering is when I am trying to map a uni-directional, one-to-many relationship where the FK is also part of a composite PK. Here are the classes and mapping file...

CompanyEntity.java

public class CompanyEntity {     private Integer id;     private Set<CompanyNameEntity> names;     ... } 

CompanyNameEntity.java

public class CompanyNameEntity implements Serializable {     private Integer id;     private String languageId;     private String name;     ... } 

CompanyNameEntity.hbm.xml

<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"         "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd">  <hibernate-mapping package="com.example">      <class name="com.example.CompanyEntity" table="COMPANY">         <id name="id" column="COMPANY_ID"/>         <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">             <key column="COMPANY_ID"/>             <one-to-many entity-name="vendorName"/>         </set>     </class>      <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME">         <composite-id>             <key-property name="id" column="COMPANY_ID"/>             <key-property name="languageId" column="LANGUAGE_ID"/>         </composite-id>         <property name="name" column="NAME" length="255"/>     </class>  </hibernate-mapping> 

This code works just fine for SELECT and INSERT of a Company with names. I encountered a problem when I tried to update and existing record. I received a BatchUpdateException and after looking through the SQL logs I saw Hibernate was trying to do something stupid...

update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=? 

Hibernate was trying to dis-associate child records before updating them. The problem is that this field is part of the PK and not-nullable. I found the quick solution to make Hibernate not do this is to add "not-null='true'" to the "key" element in the parent mapping. SO now may mapping looks like this...

CompanyNameEntity.hbm.xml

<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"         "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd">  <hibernate-mapping package="com.example">      <class name="com.example.CompanyEntity" table="COMPANY">         <id name="id" column="COMPANY_ID"/>         <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">             <key column="COMPANY_ID" not-null="true"/>             <one-to-many entity-name="vendorName"/>         </set>     </class>      <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME">         <composite-id>             <key-property name="id" column="COMPANY_ID"/>             <key-property name="languageId" column="LANGUAGE_ID"/>         </composite-id>         <property name="name" column="NAME" length="255"/>     </class>  </hibernate-mapping> 

This mapping gives the exception...

org.hibernate.MappingException: Repeated column in mapping for entity: companyName column: COMPANY_ID (should be mapped with insert="false" update="false") 

My problem now is that I have tryed to add these attributes to the key-property element but that is not supported by the DTD. I have also tryed changing it to a key-many-to-one element but that didn't work either. So...

How can I map "insert='false' update='false'" on a composite-id key-property which is also used in a one-to-many FK?

like image 699
Jesse Webb Avatar asked Feb 03 '11 23:02

Jesse Webb


People also ask

How to map composite primary key in hibernate?

We have a new tag <composite-id> tag added which lets us map composite primary key in hibernate. This tag accepts <key-property> mapping, which holds the individual property which has to be marked as primary key. In our example, empId and department will jointly act as composite primary key.

What is a composite key in a relational database?

A relational database composite key contains two or more columns which together for the primary key of a given table. In the diagram above, the employee table has a Composite Key, which consists of two columns: Every Employee can also have a Phone, which uses the same composite key to reference its owning Employee.

How to define a composite primary key in Oracle?

In order to define a composite primary key, we have used @Id annotation twice ( empId and department ). @GeneratedValue – This annotation is used to specify how the primary key should be generated. Here SEQUENCE Strategy will be used as this the default strategy for Oracle

How do I map relationships between employees in a composite key?

To see how it works, consider the following persistence logic: INSERT INTO employee (name, company_id, employee_number) We can even map relationships using the information provided within the Composite Key itself.


1 Answers

I think the annotation you are looking for is:

public class CompanyName implements Serializable { //... @JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID", insertable = false, updatable = false) private Company company; 

And you should be able to use similar mappings in a hbm.xml as shown here (in 23.4.2):

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-mappings.html

like image 96
mcyalcin Avatar answered Oct 02 '22 14:10

mcyalcin