Yet another repeated column in hibernate mapping - java

Hibernate is giving me the following exception
org.hibernate.MappingException: Repeated column in mapping for entity: Pricelist column: ID_OFFER (should be mapped with insert="false" update="false")
but I really cannot find the duplicate reference to ID_OFFER. Here they are the two mapping files involved.
Offer.hbm.xml
<hibernate-mapping>
<class name="Offer" table="OFFERS">
<id name="idOffer" type="java.lang.Long">
<column name="ID_OFFER" not-null="true" precision="10" scale="0"
sql-type="NUMBER" unique="true"/>
<generator class="native">
<param name="sequence">OFFERS_SEQ</param>
</generator>
</id>
<property generated="never" lazy="false" name="name" type="string">
<column name="name" not-null="true" sql-type="VARCHAR2" unique="true"/>
</property>
<set name="pricelists" sort="unsorted" table="PRICELISTS">
<key not-null="true">
<column name="ID_OFFER" not-null="true" precision="10" scale="0" sql-type="NUMBER"/>
</key>
<one-to-many class="Pricelist"/>
</set>
</class>
</hibernate-mapping>
Pricelist.hbm.xml
<hibernate-mapping>
<class name="Pricelist" table="PRICELISTS">
<id name="idPricelist" type="java.lang.Long">
<column name="ID_PRICELIST" not-null="true" precision="10" scale="0" sql-type="NUMBER"/>
<generator class="native">
<param name="sequence">PRICELISTS_SEQ</param>
</generator>
</id>
<property name="name" type="string">
<column length="255" name="NAME" not-null="true" sql-type="VARCHAR2"/>
</property>
<property name="versionMajor" type="integer">
<column name="VERSION_MAJOR" not-null="true" precision="5" scale="0" sql-type="NUMBER"/>
</property>
<property name="versionMinor" type="integer">
<column name="VERSION_MINOR" not-null="true" precision="5" scale="0" sql-type="NUMBER"/>
</property>
<many-to-one class="Offer" name="offer">
<column name="ID_OFFER" not-null="true" precision="10" scale="0" sql-type="NUMBER"/>
</many-to-one>
<many-to-one class="PricelistStatus" name="status">
<column name="ID_STATUS_PRICELIST" not-null="true" precision="10"
scale="0" sql-type="NUMBER"/>
</many-to-one>
<property name="validFrom" type="calendar">
<column name="INIT_TIMESTAMP" not-null="true" scale="6" sql-type="TIMESTAMP"/>
</property>
<property name="validUntil" type="calendar">
<column name="END_TIMESTAMP" not-null="false" scale="6" sql-type="TIMESTAMP"/>
</property>
</class>
</hibernate-mapping>
I am going crazy. Can anybody see where is it supposed to be duplicated the reference to the column ID_OFFER? Please note: two tables of my schema have a column named like that: OFFERS.ID_OFFER, which is the primary key of the table OFFERS and PRICELIST.ID_OFFER which has a foreign key constraint referencing, obviously, OFFERS.ID_OFFER.

You forgot about map this column as owning side (Offer.hbm.xml file)
<set name="pricelists" sort="unsorted" table="PRICELISTS">
<key not-null="true">
<column name="ID_OFFER" not-null="true" precision="10" scale="0" sql-type="NUMBER"/>
</key>
<one-to-many class="Pricelist"/>
</set>
it should look like (look at inverse="true"):
<set name="pricelists" sort="unsorted" table="PRICELISTS" inverse="true">
<key not-null="true">
<column name="ID_OFFER" not-null="true" precision="10" scale="0" sql-type="NUMBER"/>
</key>
<one-to-many class="Pricelist"/>
</set>

What #zxcf said, actually made the exception disappear, but made another question appear in my mind. Why doesn't the following mapping creates the same problem?
ServiceElement.hbm.xml
<hibernate-mapping>
<class name="ServiceElement" table="SERVICE_ELEMENTS">
<id name="idServiceElement" type="java.lang.Long">
<column name="ID_SERVICE_ELEMENT" not-null="true" precision="10"
scale="0" sql-type="NUMBER" unique="true"/>
<generator class="native">
<param name="sequence">SERVICE_ELEMENTS_SEQ</param>
</generator>
</id>
<set name="prices" table="PRICES">
<key>
<column name="ID_SERVICE_ELEMENT" not-null="true" precision="10"
scale="0" sql-type="NUMBER"/>
</key>
<one-to-many class="Price"/>
</set>
</class>
</hibernate-mapping>
Price.hbm.xml
<hibernate-mapping>
<class name="Price" table="PRICES">
<id name="idPrice" type="java.lang.Long">
<column name="ID_PRICE" not-null="true" precision="10" scale="0"
sql-type="NUMBER" unique="true"/>
<generator class="native">
<param name="sequence">PRICES_SEQ</param>
</generator>
</id>
<many-to-one class="ServiceElement" name="serviceElement">
<column name="ID_SERVICE_ELEMENT" not-null="true" precision="10"
scale="0" sql-type="NUMBER"/>
</many-to-one>
</class>
</hibernate-mapping>
Isn't it the exact same mapping? But it does not throw any exception. Here they go the DDLs:
CREATE TABLE "CE_PRICELIST"."OFFERS"
( "ID_OFFER" NUMBER(10,0),
"NAME" VARCHAR2(255 CHAR));
CREATE UNIQUE INDEX "CE_PRICELIST"."OFFERS_PK" ON "CE_PRICELIST"."OFFERS" ("ID_OFFER");
ALTER TABLE "CE_PRICELIST"."OFFERS" ADD CONSTRAINT "OFFERS_PK" PRIMARY KEY ("ID_OFFER");
CREATE TABLE "CE_PRICELIST"."PRICELISTS"
( "ID_PRICELIST" NUMBER(10,0),
"ID_OFFER" NUMBER(10,0));
CREATE UNIQUE INDEX "CE_PRICELIST"."PRICELISTS_PK" ON "CE_PRICELIST"."PRICELISTS" ("ID_PRICELIST");
ALTER TABLE "CE_PRICELIST"."PRICELISTS" ADD CONSTRAINT "PRICELISTS_PK" PRIMARY KEY ("ID_PRICELIST");
ALTER TABLE "CE_PRICELIST"."PRICELISTS" ADD CONSTRAINT "PRICELISTS_OFFER_ID_FK" FOREIGN KEY ("ID_OFFER") REFERENCES "CE_PRICELIST"."OFFERS" ("ID_OFFER") ENABLE;
CREATE TABLE "CE_PRICELIST"."SERVICE_ELEMENTS"
( "ID_SERVICE_ELEMENT" NUMBER(10,0));
CREATE UNIQUE INDEX "CE_PRICELIST"."SERVICE_ELEMENTS_PK" ON "CE_PRICELIST"."SERVICE_ELEMENTS" ("ID_SERVICE_ELEMENT");
ALTER TABLE "CE_PRICELIST"."SERVICE_ELEMENTS" ADD CONSTRAINT "SERVICE_ELEMENTS_PK" PRIMARY KEY ("ID_SERVICE_ELEMENT");
CREATE TABLE "CE_PRICELIST"."PRICES"
( "ID_PRICE" NUMBER(10,0),
"ID_SERVICE_ELEMENT" NUMBER(10,0));
CREATE UNIQUE INDEX "CE_PRICELIST"."PRICES_PK" ON "CE_PRICELIST"."PRICES" ("ID_PRICE");
ALTER TABLE "CE_PRICELIST"."PRICES" ADD CONSTRAINT "PRICES_SERVICE_ELEMENT_ID_FK" FOREIGN KEY ("ID_SERVICE_ELEMENT")
REFERENCES "CE_PRICELIST"."SERVICE_ELEMENTS" ("ID_SERVICE_ELEMENT") ENABLE;
OFFERS has a PK on ID_OFFER, which is referenced by PRICELISTS.ID_OFFER; Offer has a Set< Pricelist >;
SERVICE_ELEMENTS has a PK on ID_SERVICE_ELEMENT, which is referenced by PRICES.ID_SERVICE_ELEMENT; ServiceElement has a Set< Price >;
So why is the inverse attribute needed in one case and not in another one?

Related

Hibernate duplicates record along with null value(new row as duplicate) while saving

I am getting following issue while saving entity in hibernate -
It duplicates the record with null values -
(2661956,2601555,'Chloe','Chloe','Thooks',null,null,null,null,null,null,'Y','N','XYZ',to_date('15-NOV-16','DD-MON-RR'),null,null)
with a duplicate -
(2661946,2601555,null,null,null,null,null,null,null,null,null,'Y','N','XYZ',to_date('15-NOV-16','DD-MON-RR'),null,null) -
We have the following mapping -
Parent -
<?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="com.sm.persistence.LOADetailBO" table="LOADETAILS">
<id name="loaDetailsId" type="long">
<column name="LOA_ID" precision="38" scale="0"/>
<generator class="com.sm.persistence.dao.seqgen.LOADetailSeqGen">
</generator>
</id>
<many-to-one name="reregistration" class="com.sm.persistence.RerBO" fetch="join">
<column name="RER_ID" precision="38" scale="0"/>
</many-to-one>
<property name="relatedPlanManager" type="string">
<column name="RELATED_PLAN_MANAGER"/>
</property>
<property name="relatedPlanManagerCode" type="string">
<column name="RELATED_PLAN_MANAGER_CODE"/>
</property>
<set name="relatedPlanManagerAddress" inverse="true" cascade="all-delete-orphan">
<key>
<column name="LOA_ID" precision="38" scale="0" not-null="false"/>
</key>
<one-to-many class="com.sm.persistence.AddressBO" />
</set>
<set name="corporateCustomers" inverse="true" cascade="all-delete-orphan">
<key>
<column name="LOA_ID" precision="38" scale="0" not-null="false"/>
</key>
<one-to-many class="com.sm.persistence.CorporateCustomerBO" />
</set>
<set name="privateCustomers" inverse="true" cascade="all-delete-orphan">
<key>
<column name="LOA_ID" precision="38" scale="0" not-null="false" />
</key>
<one-to-many class="com.sm.persistence.PrivateCustomerBO"/>
</set>
<set name="unwrappedAccount" inverse="true" cascade="all-delete-orphan">
<key>
<column name="LOA_ID" precision="38" scale="0" not-null="false"/>
</key>
<one-to-many class="com.sm.persistence.UnwrappedAccountBO" />
</set>
<set name="wrappedAccount" inverse="true" cascade="all-delete-orphan">
<key>
<column name="LOA_ID" precision="38" scale="0" not-null="false" />
</key>
<one-to-many class="com.sm.persistence.WrappedAccountBO"/>
</set>
</class>
</hibernate-mapping>
Child -
<?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="com.sm.persistence.PrivateCustomerBO" table="RER_CUSTOMER_DETAIL">
<id name="privateCustomerId" type="long">
<column name="RERE_CUSTOMER_ID" precision="38" scale="0"/>
<generator class="com.sm.persistence.dao.seqgen.PrivateCustomerSeqGen">
</generator>
</id>
<many-to-one name="loaDetail" class="com.sm.persistence.LOADetailBO" fetch="join">
<column name="LOA_DETAILS_ID" precision="38" scale="0"/>
</many-to-one>
<property name="title" type="string">
<column name="TITLE"/>
</property>
<property name="firstName" type="string">
<column name="FIRST_NAME"/>
</property>
<property name="surname" type="string">
<column name="SURNAME"/>
</property>
<set name="address" inverse="false" cascade="all-delete-orphan">
<key>
<column name="PRIVATE_CUSTOMER_ID" precision="38" scale="0" not-null="false"/>
</key>
<one-to-many class="com.sm.persistence.AddressBO" />
</set>
<property name="primary" type="string">
<column name="IS_PRIMARY"/>
</property>
<property name="corporate" type="string">
<column name="IS_CORPORATE"/>
</property>
<!--<property name="dateofBirth" type="string">
<column name="DATE_OF_BIRTH"/>
</property>-->
<property name="nationalInsurance" type="string">
<column name="NINO"/>
</property>
</class>
</hibernate-mapping>
I checked parent object both pre and post save and can't find any object with null value populated. However, when I fetch the object hierarchy with criteria api it returns duplicate record with null.
Please guide.
Quick answer:
PrivateCustomerBO is a child of LOADetailBO. So when your java code
saves a PrivateCustomerBO object it will write to all tables
specified against these 2 objects: RER_CUSTOMER_DETAIL = primary
table for PrivateCustomerBO, LOADETAILS = primary table for
LOADetailBO, plus all tables referenced by these two objects via
many-to-one or one-to-many mappings. CORRECT BEHAVIOUR
Expanding the bolded bit above, LOADetailBO is referenced by
PrivateCustomerBO via:
<many-to-one name="loaDetail" class="com.sm.persistence.LOADetailBO" fetch="join">
<column name="LOA_DETAILS_ID" precision="38" scale="0"/>
</many-to-one>
This means that LOADETAILS is additionally referenced as a related
table, not just a parent and a second row is written (in this case
there is some data missing (NULL) because your program hasn't
populated it for the referenced entity). INCORRECT BEHAVIOUR.
Fix: remove the many-to-one mapping shown above (it's redundant and covered by parent).

HQL equivalent query to criteria query in hibernate many to many relationship?

I have two tables stock and category having many-to-many relationship each other.
Stock.hbm.xml
<hibernate-mapping>
<class name="hibernate.mapping.manytomany.Stock" table="stock">
<id name="stockId" type="java.lang.Integer">
<column name="STOCK_ID" />
<generator class="identity" />
</id>
<property name="stockCode" type="string">
<column name="STOCK_CODE" length="10" not-null="true" unique="true" />
</property>
<property name="stockName" type="string">
<column name="STOCK_NAME" length="20" not-null="true" unique="true" />
</property>
<set name="categories" table="stock_category"
inverse="false" lazy="true" fetch="select" cascade="all" >
<key>
<column name="STOCK_ID" not-null="true" />
</key>
<many-to-many entity-name="hibernate.mapping.manytomany.Category">
<column name="CATEGORY_ID" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
Category.hbm.xml
<hibernate-mapping>
<class name="hibernate.mapping.manytomany.Category" table="category">
<id name="categoryId" type="java.lang.Integer">
<column name="CATEGORY_ID" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="NAME" length="10" not-null="true" />
</property>
<property name="desc" type="string">
<column name="[DESC]" not-null="true" />
</property>
<set name="stocks" table="stock_category" inverse="true" lazy="true"
fetch="select">
<key>
<column name="CATEGORY_ID" not-null="true" />
</key>
<many-to-many entity-name="hibernate.mapping.manytomany.Stock">
<column name="STOCK_ID" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
And this is my criteria query,
Criteria c = session.createCriteria(Category.class, "c");
c.createAlias("c.stocks", "s");
c.add(Restrictions.eq("c.categoryId", 1));
c.setProjection(Projections.projectionList()
.add(Projections.property("s.stockId"))
.add(Projections.property("s.stockName")));
I need equivalent HQL for this scenario..I've tried this but it gives different result,
String query = "select c.stocks.stockId, c.stocks.stockName from Category c where
c.categoryId=1"
Let me know if you need more details.
OK, so apparently, you missed the section about joins in the documentation:
select s.stockId, // equivalent to the s.stockId projection
s.stockName // equivalent to the s.stockName projection
from Category c // equivalent to the root criteria creation
join c.stocks s // equivalent to the alias creation
where c.categoryId = 1 // equivalent to the restriction addition
I am planning to investigate this issue thoroughly. What i doubt from previous answer for now is there should be ON Clause in join statement. Pardon me if my expectation is wrong.
select s.stockId,s.stockName from Category c join c.stocks s
on c.stockId=s.stockId where c.categoryId = 1 ;
//it might be on c.CATEGORY_ID=s.CATEGORY_ID also

Hibernate fetches one more column that is an arbitrary integer

I'm seeing this weird console output
Hibernate:
select
simplematc0_.id as id1_74_0_,
simplematc0_.master_id as master_i2_74_0_,
simplematc0_.slave_code as slave_co3_74_0_,
simplematc0_.slave_grade as slave_gr4_74_0_
from
match_slave simplematc0_
where
simplematc0_.id=?
10:07:38,713 TRACE BasicBinder:84 - binding parameter [1] as [BIGINT] - 68
10:07:38,715 TRACE BasicExtractor:74 - Found [0] as column [master_i2_74_0_]
10:07:38,715 TRACE BasicExtractor:74 - Found [test12] as column [slave_co3_74_0_]
10:07:38,715 TRACE BasicExtractor:74 - Found [1] as column [slave_gr4_74_0_]
10:07:38,715 TRACE BasicExtractor:74 - Found [1] as column [slave_gr4_74_0_]
10:07:38,716 TRACE BasicExtractor:74 - Found [1937012087] as column [slave_co3_74_0_]
I queried for 4 columns and Hibernate returns 5 columns. I need the value "test12" but it keeps returning "1937012087" which I could not find in any of my tables.
Why is Hibernate getting this weird value ?
properties.match.master.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class table="match_master" name="properties.match.SimpleMatchMaster">
<id name="id">
<generator class="sequence">
<param name="sequence">
seq_matching_item_codes_pk
</param>
</generator>
</id>
<property name="masterCode">
<column name="master_code"/>
</property>
<property name="masterName">
<column name="MASTER_NAME"/>
</property>
<property name="masterGrade">
<column name="master_grade"/>
</property>
<property name="isInUse">
<column name="default_in_use_id"></column>
</property>
<many-to-one name="useStatus" class="properties.SimpleIsInUse" fetch="select"
insert="false" update="false" lazy="false" not-null="false" not-found="ignore">
<column name="default_in_use_id"></column>
</many-to-one>
<many-to-one name="masterObject" class="foreign.Mea_class_no"
not-found="ignore" not-null="false" update="false" insert="false"
fetch="select" lazy="false"
>
<column name="master_code"></column>
<column name="master_grade"></column>
</many-to-one>
<set name="matchSlaves" table="jnc_match_master_slave"
order-by="slave_id"
lazy="false" fetch="select" cascade="all, delete-orphan" >
<key column="master_id" ></key>
<many-to-many class="properties.match.SimpleMatchSlave" not-found="ignore"
fetch="select" >
<column name="slave_id"></column>
</many-to-many>
</set>
<set name="matchHistory" table="jnc_match_history"
order-by="history_id" lazy="false" fetch="select"
cascade="all, delete-orphan, delete, persist"
>
<key>
<column name="master_id"></column>
</key>
<many-to-many class="properties.match.SimpleMatchHistory"
foreign-key="master_id"
>
<column name="history_id"></column>
</many-to-many>
</set>
</class>
</hibernate-mapping>
properties.match.slave.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class table="match_slave" name="properties.match.SimpleMatchSlave"
select-before-update="true"
>
<id name="id" type="long" >
<column name="id" />
<generator class="sequence">
<param name="sequence">seq_match_slave_pk</param>
</generator>
</id>
<property name="masterId" not-null="false">
<column name="master_id"></column>
</property>
<property name="slaveCode" not-null="false">
<column name="slave_code"></column>
</property>
<property name="slaveGrade" not-null="false">
<column name="slave_grade"></column>
</property>
<many-to-one name="slaveObject" class="foreign.Mea_class_no"
fetch="select"
insert="false" update="false" lazy="false" not-found="ignore" not-null="false"
>
<column name="slave_grade"></column>
<column name="slave_code"></column>
</many-to-one>
</class>
</hibernate-mapping>
I've solved it by changing the order of the two columns which were working as a composite foreign key.
Before
<many-to-one name="slaveObject" class="foreign.Mea_class_no"
fetch="select"
insert="false" update="false" lazy="false" not-found="ignore" not-null="false"
>
<column name="slave_grade"></column>
<column name="slave_code"></column>
</many-to-one>
After
<many-to-one name="slaveObject" class="foreign.Mea_class_no"
fetch="select"
insert="false" update="false" lazy="false" not-found="ignore" not-null="false"
>
<column name="slave_code"></column>
<column name="slave_grade"></column>
</many-to-one>

one to many relation with column other than Id (Primary Key)

I am trying to map two tables using hibernate one-to-many mapping. But, always it is mapping with the wrong column. Please any body help me on this.
Level4_Master [level_id (PK/Auto Increament), company_id, level_name, next_level_id, ts]
Level3_Master [level_id (PK/Auto Increament), prv_level_id, level_name, next_level_id, ts]
Above are the two tables I am using for the mapping. Here, I wanted to map column next_level_id of Level4_Master with column prv_level_id of Level3_Master. But, hibernate always mapping the column prv_level_id with level_id of Level4_Master as FK. My mapping files are:
<hibernate-mapping>
<class name="com.pojo.Level4" table="Level4_Master">
<id name="levelId" type="java.lang.Integer">
<column name="level_id" />
<generator class="increment" />
</id>
<property name="companyId" >
<column name="company_id" length="10" not-null="true" unique="true" />
</property>
<property name="levelName">
<column name="level_name" length="20" not-null="true" unique="true" />
</property>
<property name="nextLevelId" type="java.lang.Integer">
<column name="next_level_id" />
</property>
<set name="levelList" table="Level3_Master" inverse="true" lazy="true" fetch="select">
<key>
<column name="prv_level_id" not-null="true" />
</key>
<one-to-many class="com.pojo.Level3" />
</set>
</class>
</hibernate-mapping>
and
<hibernate-mapping>
<class name="com.pojo.Level3" table="Level3_Master">
<id name="levelId" type="java.lang.Integer">
<column name="level_id" />
<generator class="increment" />
</id>
<property name="prvLevelId" >
<column name="prv_level_id" length="10" not-null="true" unique="true" />
</property>
<property name="levelName">
<column name="level_name" length="20" not-null="true" unique="true" />
</property>
<property name="nextLevelId" type="java.lang.Integer">
<column name="next_level_id" />
</property>
<set name="levelList" table="Level2_Master" inverse="true" lazy="true" fetch="select">
<key>
<column name="prv_level_id" not-null="true" />
</key>
<one-to-many class="com.pojo.Level2" />
</set>
</class>
</hibernate-mapping>
and my pojo classes are like
class Level4{
private int levelId;
private int companyId;
private String levelName;
private int nextLevelId;
private Set<Level3> levelList = new HashSet<Level3>(0);
private Timestamp ts;
//getter n setter
}
class Level3{
private int levelId;
private int prvLevelId;
private String levelName;
private int nextLevelId;
private Set<Level2> levelList = new HashSet<Level2>(0);
private Timestamp ts;
//getter n setter
}
You need to use property-ref attribute with the property name. The property must add unique="true" in the property mapping.
Example -
<hibernate-mapping><class name="com.pojo.Level4" table="Level4_Master">
<id name="levelId" type="java.lang.Integer">
<column name="level_id" />
<generator class="increment" />
</id>
<property name="companyId" >
<column name="company_id" length="10" not-null="true" unique="true" />
</property>
<property name="levelName">
<column name="level_name" length="20" not-null="true" unique="true" />
</property>
<property name="nextLevelId" type="java.lang.Integer" unique="true">
<column name="next_level_id" />
</property>
<set name="levelList" table="Level3_Master" inverse="true" lazy="true" fetch="select">
<key>
<column name="prv_level_id" not-null="true" property-ref="nextLevelId"/>
</key>
<one-to-many class="com.pojo.Level3" />
</set>

org.hibernate.MappingException: Foreign key (FK12A711396456CA10:) must have same number of columns as the referenced primary key

I'm having this error at Netbeans in my Java code:
org.hibernate.MappingException: Foreign key (FK12A711396456CA10:devolucion_master [devolucion_consecutivo])) must have same number of columns as the referenced primary key (devolucion [detalle_ticket_id,detalle_ticket_ticket_id,detalle_ticket_fondo_fijo_id,detalle_ticket_caja_id,consecutivo]
I made a foreign key from DevolucionMaster to Devolucion, using "consecutivo" from Devolucion to my variable "consecutivo" for DevolucionMaster, the problem is that for Devolucion the "key" is composite key, and I only use for the foreign key one element of the key, maybe that's why (that it needs to be used the 5 that makes the primary key).
Here's the DevolucionMaster.hbm.mxl:
<hibernate-mapping>
<class catalog="pos" name="dunosusa.pos.model.DevolucionMaster" table="devolucion_master">
<composite-id class="dunosusa.pos.model.DevolucionMasterId" name="id">
<key-property name="id" type="int">
<column name="id"/>
</key-property>
<key-property name="detalleTicketTicketId" type="int">
<column name="detalle_ticket_ticket_id"/>
</key-property>
<key-property name="detalleTicketFondoFijoId" type="int">
<column name="detalle_ticket_fondo_fijo_id"/>
</key-property>
<key-property name="detalleTicketCajaId" type="int">
<column name="detalle_ticket_caja_id"/>
</key-property>
</composite-id>
<many-to-one class="dunosusa.pos.model.Devolucion" fetch="select" name ="devolucion">
<column name="devolucion_consecutivo" not-null="true"/>
</many-to-one>
<many-to-one class="dunosusa.pos.model.Usuario" fetch="select" name="usuario">
<column length="6" name="usuario_clave_autorizo"/>
</many-to-one>
<many-to-one class="dunosusa.pos.model.Ticket" fetch="select" insert="false" name="ticket" update="false">
<column name="detalle_ticket_ticket_id" not-null="true"/>
<column name="detalle_ticket_fondo_fijo_id" not-null="true"/>
<column name="detalle_ticket_caja_id" not-null="true"/>
</many-to-one>
<property name="total" type="big_decimal">
<column name="total" not-null="true" precision="10"/>
</property>
<property name="fecha" type="timestamp">
<column length="19" name="fecha"/>
</property>
</class>
</hibernate-mapping>
here the Devolucion.hbm.xml:
<hibernate-mapping>
<class catalog="pos" name="dunosusa.pos.model.Devolucion" table="devolucion">
<composite-id class="dunosusa.pos.model.DevolucionId" name="id">
<key-property name="detalleTicketId" type="int">
<column name="detalle_ticket_id"/>
</key-property>
<key-property name="detalleTicketTicketId" type="int">
<column name="detalle_ticket_ticket_id"/>
</key-property>
<key-property name="detalleTicketFondoFijoId" type="int">
<column name="detalle_ticket_fondo_fijo_id"/>
</key-property>
<key-property name="detalleTicketCajaId" type="int">
<column name="detalle_ticket_caja_id"/>
</key-property>
<key-property name="consecutivo" type="int">
<column name="consecutivo"/>
</key-property>
</composite-id>
<many-to-one class="dunosusa.pos.model.MotivoDevolucion" fetch="select" name="motivoDevolucion">
<column name="motivo_devolucion_id" not-null="true"/>
</many-to-one>
<many-to-one class="dunosusa.pos.model.DetalleTicket" fetch="select" insert="false" name="detalleTicket" update="false">
<column name="detalle_ticket_id" not-null="true"/>
<column name="detalle_ticket_ticket_id" not-null="true"/>
<column name="detalle_ticket_fondo_fijo_id" not-null="true"/>
<column name="detalle_ticket_caja_id" not-null="true"/>
</many-to-one>
<many-to-one class="dunosusa.pos.model.ControlCorte" fetch="select" name="controlCorte">
<column name="control_corte_fondo_fijo_id" not-null="true"/>
<column name="control_corte_caja_id" not-null="true"/>
</many-to-one>
<property name="cantidad" type="big_decimal">
<column name="cantidad" precision="8"/>
</property>
<property name="fecha" type="timestamp">
<column length="19" name="fecha"/>
</property>
<property name="comentario" type="string">
<column length="150" name="comentario"/>
</property>
<property name="controlDevolucion" type="boolean">
<column name="control_devolucion" not-null="true"/>
</property>
<set name="devolucionMasters" inverse="true">
<key>
<column name="devolucion_consecutivo" not-null="true" />
</key>
<one-to-many class="dunosusa.pos.model.DevolucionMaster" />
</set>
</class>
</hibernate-mapping>
DevolucionMaster.java: (only the variables, not the set and get)
public class DevolucionMaster implements java.io.Serializable {
private DevolucionMasterId id;
private Devolucion devolucion;
private Usuario usuario;
private Ticket ticket;
private BigDecimal total;
private Date fecha;
}
Devolucion.java: (same as for DevolucionMaster)
public class Devolucion implements java.io.Serializable {
private DevolucionId id;
private MotivoDevolucion motivoDevolucion;
private DetalleTicket detalleTicket;
private ControlCorte controlCorte;
private BigDecimal cantidad;
private Date fecha;
private String comentario;
private boolean controlDevolucion;
private Set devolucionMasters = new HashSet(0);
}
I don't know what's my error, I've searched over internet about similar errors but no one solution I've read has worked (forgive my bad english).
Thanks a lot!
Yes, you have a composite primary key for the Devolucion class, and you are trying to refer to it by just one simple column/field devolucion_master.devolucion_consecutivo.
I don't know of a way to easily tell Hibernate that devolucion_consecutivo column is actually of type dunosusa.pos.model.DevolucionId.
That's why I have never used composite primary keys. I always have one primary key of type Long (bigint) and enforce uniqueness for a composition of foreign keys where it's needed. It's easier to work with, no issues like the one you're having.
APPENDIX:
I just did some digging and, actually, there is a way to do it :-)
But as I said it's not as easy as using single column PK/FK keys.
Instead of this:
<hibernate-mapping>
<class catalog="pos" name="dunosusa.pos.model.DevolucionMaster" table="devolucion_master">
...
<many-to-one class="dunosusa.pos.model.Devolucion" fetch="select" name="devolucion">
<column name="devolucion_consecutivo" not-null="true"/>
</many-to-one>
...
You should list all PK columns in the FK like this:
<hibernate-mapping package="dunosusa.pos.model">
<class catalog="pos" name="DevolucionMaster" table="devolucion_master">
...
<many-to-one class="Devolucion" fetch="select" name="devolucion">
<column name="devolucion_detalle_ticket_id" not-null="true"/>
<column name="devolucion_detalle_ticket_ticket_id" not-null="true"/>
<column name="devolucion_detalle_ticket_fondo_fijo_id" not-null="true"/>
<column name="devolucion_detalle_ticket_caja_id" not-null="true"/>
<column name="devolucion_consecutivo" not-null="true"/>
</many-to-one>
...
A little advice - use the package attribute of the hibernate-mapping element so you don't have to type it in everywhere - it makes it more readable.
Good luck.

Categories