Say I have three tables in a many-to-many: user, group, and user_in_group. The structure of the many-to-many is:
user_id BIGINT
group_id BIGINT
generate_table TINYINT
Which should result in:
public UserInGroup(UserInGroupId id = new UserInGroupId(user_id, group_id),
User user,
Group group,
boolean generateTable)
But instead, it results in:
public UserInGroup(UserInGroupId id = new UserInGroupId(user_id, group_id),
Group group,
User user,
boolean generateTable)
I thought it might be that the foreign key for group was created before the foreign key for user, but I swapped the foreign keys and it make no difference.
Here is my UserInGroup.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Aug 1, 2014 10:06:06 AM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.my.project.UserInGroup" table="user_in_group" catalog="project">
<composite-id name="id" class="com.my.project.UserInGroupId">
<key-property name="UserId" type="long">
<column name="user_id" />
</key-property>
<key-property name="GroupId" type="long">
<column name="group_id" />
</key-property>
</composite-id>
<many-to-one name="Group" class="com.my.project.Group" update="false" insert="false" fetch="select">
<column name="group_id" not-null="true" />
</many-to-one>
<many-to-one name="User" class="com.my.project.User" update="false" insert="false" fetch="select">
<column name="user_id" not-null="true" />
</many-to-one>
<property name="generateTable" type="boolean">
<column name="generate_table" not-null="true" />
</property>
</class>
</hibernate-mapping>
The order of the properties in the generated constructors corresponds to the order of the properties within the XML Mapping.
In the mapping for the composite key, the userId is first, then the groupId. Hence you get new UserInGroupId(user_id, group_id). For the many-to-one references, it is vice-versa - the reference to the Group is stated first, then the reference to the User.
You can simply change the XML and switch the order of the many-to-one references:
<many-to-one name="User" class="com.my.project.User" update="false" insert="false" fetch="select">
<column name="user_id" not-null="true" />
</many-to-one>
<many-to-one name="Group" class="com.my.project.Group" update="false" insert="false" fetch="select">
<column name="group_id" not-null="true" />
</many-to-one>
Since the XML is generated from reverse engeneering, the database that you reverse engeneer probably returns the two foreign keys in the order that you see in the generated XML. If you do not want to manually change the XML, you should check, if you can modify the source database to return the columns in your desired order.
Related
I'm facing a problem with class mapping in hibernate.
I'm trying to make a many-to-one relationship using a composite-id.
and the mapping is returning
Repeated column in mapping for entity:
br.com.is.isenterprise.cre.model.ClienteRegraIcmsMap column: EMPRESAID
(should be mapped with insert="false" update="false")
but if I set the many-to-one relationship to insert =" false " and update =" false I can not insert the id of regraIcmsSubistituta in the database.
follows the hbm files.
RegraIcms.hbm.xml
<hibernate-mapping package="br.com.is.isenterprise.efi.model">
<class name="RegraIcms" table="REGRAICMS">
<composite-id name="cid" class="br.com.is.isenterprise.efi.model.RegraIcmsId">
<key-property name="empCod" type="integer" column="EMPCOD"/>
<key-property name="idRegraIcms" type="integer" column="IDREGRAICMS"/>
</composite-id>
<property name="descricao" type="string" column="DESCRICAO" access="field"/>
<property name="aplicacao" type="integer" column="APLICACAO" access="field"/>
</class>
</hibernate-mapping>
ClienteRegraIcmsMapId.hbm.xml
<class name="ClienteRegraIcmsMap" table="CLIENTEREGRAICMSMAP">
<composite-id name="cid" class="br.com.is.isenterprise.cre.model.ClienteRegraIcmsMapId">
<key-many-to-one name="cliente" column="CLIENTEID" class="br.com.is.isenterprise.cre.model.Cliente" access="field" lazy="false"/>
<key-many-to-one name="regraIcms" class="br.com.is.isenterprise.efi.model.RegraIcms" access="field" lazy="false">
<column name="EMPRESAID"/>
<column name="REGRAICMSID"/>
</key-many-to-one>
</composite-id>
<version name="versao" type="integer" column="VERSAO"/>
<many-to-one name="regraIcmsSubstituta" class="br.com.is.isenterprise.efi.model.RegraIcms" access="field" lazy="false">
<column name="EMPRESAID"/>
<column name="REGRAICMSSUBSTITUTAID"/>
</many-to-one>
</class>
</hibernate-mapping>
You're trying to use the same column (EMPRESAID) for two different things, the primary key as well as the many-to-one relation.
That's not gonna work (except with insertable = "false", as you mentioned)
If it's possible use a separate column for EMPRESAID in one of the mappings.
I am working on an application that saves employee data using jsf 1.2, richfaces 3.3, for ORM i am using hibernate 3. I am saving data in 'Employee' basic table about two fields i.e Present City and Permanent City. The City values come from a lookup table 'City' . my hbm file for the employee table has following code:-
<many-to-one name="presentcity" cascade="lock" column="PRESENT_CITY_ID"
class="org.lookups.City" lazy="false">
</many-to-one>
<many-to-one name="permanentcity" cascade="lock" column="PERM_CITY_ID"
class="org.lookups.City" lazy="false">
</many-to-one>
this question did not help as it uses annotations and i need to work with hbm file. The problem is, when i update one of the presentcity or permanentcity, both the values are changed.
structure of my tables is as follows:-
employee table
________________________________________________________
emp_id name age PRESENT_CITY_ID PERM_CITY_ID
________________________________________________________
203 paul 28 3 7
. . . . .
301 ferris 29 6 9
_________________________________________________________
city lookup table
______________________
id city
______________________
3 Chicago
. .
6 Cairo
. .
9 Wales
______________________
The hibernate.cfg.hbm files for both employee and city are as follows:-
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.Employee" table="EMP_MAIN">
<id name="empId" type="long" column="EMP_ID">
<generator class="increment"></generator>
</id>
<property name="emp_No" type="long" column="EMP_NO" />
<property name="name" type="string" column="NAME" />
<many-to-one name="presentcity" class="org.lookups.City"
fetch="select" cascade="none">
<column name="PRESENT_CITY_ID" precision="22" scale="0"
not-null="false">
<comment>present city of the employee</comment>
</column>
</many-to-one>
<many-to-one name="permanentcity" class="org.lookups.City"
fetch="select" cascade="none">
<column name="PERM_CITY_ID" precision="22" scale="0"
not-null="false">
<comment>permanent city of the employee</comment>
</column>
</many-to-one>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.lookups.City" table="LU_CITY">
<id name="id" type="long" column="CITY_ID">
<generator class="increment"></generator>
</id>
<property name="city" type="string" column="CITY_NAME" />
</class>
</hibernate-mapping>
how to get around this problem.
I've adapted this from a working hbm file that we use at our company so I know it works. It includes the column name for mapping. Maybe that is what you're missing?
<many-to-one name="presentcity" class="org.lookups.City" fetch="select" cascade="none">
<column name="PRESENT_CITY_ID" precision="22" scale="0" not-null="false">
<comment>the present city of the employee</comment>
</column>
</many-to-one>
<many-to-one name="permanentcity" class="org.lookups.City" fetch="select" cascade="none">
<column name="PERM_CITY_ID" precision="22" scale="0" not-null="false">
<comment>the permanent city of the employee</comment>
</column>
</many-to-one>
Good luck.
I'm stuck at the hibernate xml mapping configuration.
I've established some tables with foreign key constraints in my MSSQL database:
Table ItemsBase
ID int primary-key
ItemID int unique index
... some more columns
Table Others
ID int primary-key
ItemID int unique index
... some more columns
The foreign key constraint is configured to connect these two tables by using the column "ItemID".
My ItemsBase.hbm.xml files looks like:
<hibernate-mapping>
<class name="de.delife.sql.ItemsBase" table="ItemsBase" schema="dbo" catalog="Delife_Plenty">
<id name="id" type="int">
<column name="ID" />
<generator class="assigned" />
</id>
<property name="itemId" type="java.lang.Integer">
<column name="ItemID" unique="true" />
</property>
<set name="otherses" table="Others" inverse="true" lazy="true" fetch="select">
<key property-ref="itemId">
<column name="ItemID" />
</key>
<one-to-many class="de.delife.sql.Others" not-found="ignore" />
</set>
</class>
</hibernate-mapping>
and the Others.hbm.xml files looks like:
<hibernate-mapping>
<class name="de.delife.sql.Others" table="Others" schema="dbo" catalog="Delife_Plenty">
<id name="id" type="int">
<column name="ID" />
<generator class="assigned" />
</id>
<many-to-one name="itemsBase" class="de.delife.sql.ItemsBase" fetch="select" property-ref="itemId">
<column name="ItemID" unique="true" />
</many-to-one>
</class>
</hibernate-mapping>
Everything looks fine for me, but when I run my program I get a hibernate error:
property [itemId] not found on entity [de.delife.sql.Others]
I have an established relation between ItemsBase and a table named ItemsProperties and it works, but with this "pretty" table "Others" I'm stuck.
I would be glad, if someone can help me on this matter. Thx in advance.
Try like this. I tried and its working for me.
<set name="otherses" table="Others" inverse="true" lazy="true" fetch="select">
<key column="itemId" foreign-key="itemId" property-ref="itemId"/>
<one-to-many class="de.delife.sql.Others" not-found="ignore" />
</set>
Item id should be defined as a property in Others.hbm.xml:
<property name="itemId" column="ItemId"/>
I have 3 tables:
Account
{
Long account_id; // primary key, alternate key field 1
Long client_id; // alternate key field 2
...
}
Admin
{
Long office_id; // primary key field 1
Long account_id; // primary key field 2
Long client_id;
}
Office
{
Long office_id; // primary key
...
}
So the Admin table references Account table by alternate key (of account_id, client_id). I try to write mapping for it but cant understand how.
I have now:
<class name="Account" table="Account">
<id name="id">
<column name="account_id" not-null="true"/>
</id>
<properties name="account_ak1" unique="true">
<property name="id" column="account_id" insert="false" update="false"/>
<property name="client" column="client_id" insert="false" update="false"/>
</properties>
<many-to-one name="client" class="Client" column="client_id" lazy="false" fetch="join"/>
...
</class>
<class name="Admin">
<composite-id name="id" class="KeyPair">
<key-many-to-one name="t1" class="Office" column="office_id" lazy="false"/>
<key-many-to-one name="t2" class="Account" lazy="false" column="account_id"/>
</composite-id>
<many-to-one name="account" class="Account" not-null="true" insert="false" update="false" lazy="false" fetch="join" property-ref="account_ak1">
<column name="account_id"/>
<column name="client_id"/>
</many-to-one>
</class>
The problem is that i cant set client_id in sql update/insert this way and i cant set only account_id to insert/update false neither within composite-id nor within many-to-one.
Also, i tried to include all the fields of Account in primary key.
<composite-id name="id" class="KeyPair">
<key-many-to-one name="t1" class="Office" column="office_id" lazy="false"/>
<key-many-to-one name="t2" class="Account" lazy="false"/>
<column name="account_id"/>
<column name="client_id"/>
</key-many-to-one>
</composite-id>
but key-many-to-one can reference only primary key of Account and does not accept property-ref.
How to solve this?
I'm building a data warehouse and want to use InfiniDB as the storage engine. However, it doesn't allow primary keys or foreign key constraints (or any constraints for that matter).
Hibernate complains "The database returned no natively generated identity value" when I perform an insert.
Each table is relational, and contains a unique integer column that was previously used as the primary key - I want to keep that, but just not have the constraint in the db that the column is the primary key.
I'm assuming the problem is that Hibernate expects the db to return a generated key. Is it possible to override this behaviour so I can set the primary key field's value myself and keep Hibernate happy?
-- edit --
Two of the mappings are as follows:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jun 1, 2010 2:49:51 PM by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
<class name="com.example.project.Visitor" table="visitor" catalog="orwell">
<id name="id" type="java.lang.Long">
<column name="id" />
<generator class="identity" />
</id>
<property name="firstSeen" type="timestamp">
<column name="first_seen" length="19" />
</property>
<property name="lastSeen" type="timestamp">
<column name="last_seen" length="19" />
</property>
<property name="sessionId" type="string">
<column name="session_id" length="26" unique="true" />
</property>
<property name="userId" type="java.lang.Long">
<column name="user_id" />
</property>
<set name="visits" inverse="true">
<key>
<column name="visitor_id" />
</key>
<one-to-many class="com.example.project.Visit" />
</set>
</class>
</hibernate-mapping>
and:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jun 1, 2010 2:49:51 PM by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
<class name="com.example.project.Visit" table="visit" catalog="orwell">
<id name="id" type="java.lang.Long">
<column name="id" />
<generator class="identity" />
</id>
<many-to-one name="visitor" class="com.example.project.Visitor" fetch="join" cascade="all">
<column name="visitor_id" />
</many-to-one>
<property name="visitId" type="string">
<column name="visit_id" length="20" unique="true" />
</property>
<property name="startTime" type="timestamp">
<column name="start_time" length="19" />
</property>
<property name="endTime" type="timestamp">
<column name="end_time" length="19" />
</property>
<property name="userAgent" type="string">
<column name="user_agent" length="65535" />
</property>
<set name="pageViews" inverse="true">
<key>
<column name="visit_id" />
</key>
<one-to-many class="com.example.project.PageView" />
</set>
</class>
</hibernate-mapping>
As you noted in a comment, there're many id generators you can use. E.g., you many find 'increment' convenient. Complete overview
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id
And hibernate won't care about your db restrictions (both primary keys and foreign keys). In fact, hibernate has no way of knowing about certain db restriction until it's violated. And if restriction doesn't exist, it can never be violated :)
You can remove the <generator class="identity" /> element and set the id manually before saving the object.