I try to write mapping to tables. I decided that id and versionId - composite-id for table test. But in table test_question I have composite-id consists from question_id, test_id and versionId. I can't understand as I can use one composite-id id-versionId as part other composite-id.
I have next peace of script.
Create Table Test
(
id int unsigned not null,
versionId int unsigned not null,
test_text varchar(200) not null,
subject_id int unsigned not null,
primary key (id, versionId),
Foreign key (subject_id) REferences Subject(id)
On delete cascade on update cascade
)
Engine InnoDB CHARACTER SET utf8;
Create Table Question
(
id varchar(36) not null,
question_text varchar(200) not null,
primary key(id)
)
Engine InnoDB CHARACTER SET utf8;
Create table Test_Question
(
test_id int unsigned not null,
question_id varchar(36) not null,
versionId int unsigned not null,
primary key(test_id, question_id, versionId),
Foreign key(test_id,versionId) References Test(id, versionId),
Foreign key(question_id) References Question(id)
)
Engine InnoDB CHARACTER SET utf8;
And my mapping
Test.hbm.xml
<hibernate-mapping>
<class name="by.bsuir.testapp.model.Test" table="TEST">
<composite-id>
<key-property name="testId" type="long" column="TEST_ID" />
<key-property name="versionId" type="long" column="VERSION_ID" />
<generator class="assigned"/>
</composite-id>
<property name="testName" type="string">
<column name="TESTNAME" />
</property>
<many-to-one name="subject" class="by.bsuir.testapp.model.Subject"
fetch="join">
<column name="SUBJECT_ID" />
</many-to-one>
</class>
</hibernate-mapping>
and for TestQuestion.hbm.xml
<hibernate-mapping>
<class name="by.bsuir.testapp.model.TestQuestion" table="TEST_QUESTION">
<composite-id>
<key-property name="test" type="long" column="TEST_ID" />
<key-property name="question" type="long" column="QUESTION_ID" />
<generator class="assigned" />
</composite-id>
</class>
</hibernate-mapping>
What should be id in table TestQuestion? I mean that QUESTION_ID-TEST_ID-VERSION_ID is whole composite id.
Related
I want to create the following tables with the necessary associations accordingly:
However, it seems that I have miyed up something because when Hibernate creates the tables multiple foreign keys are created as shown below:
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess
[org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess#5e5595f3]
for (non-JTA) DDL execution was not in auto-commit mode; the
Connection 'local transaction' will be committed and the Connection
will be set into auto-commit mode.
Hibernate: create table APP.ITEMS (ITEM_ID integer generated by
default as identity, NAME varchar(100), NET_PRICE integer, VAT_RATE
integer, CATEGORY_ID integer not null, primary key (ITEM_ID))
Hibernate: create table APP.LIMIT (LIMIT_ID integer not null,
LIMIT_VALUE integer, primary key (LIMIT_ID))
Hibernate: create table APP.PARTNER (PARTNER_ID integer generated by
default as identity, PARTNER_NAME varchar(100), primary key
(PARTNER_ID))
Hibernate: create table APP.TRANSACTIONS (TRANSACTIONS_ID integer
generated by default as identity, FLOW integer not null, NET_PRICE
integer, ITEM_ID integer not null, advicenote integer, ADVICENOTE_ID
integer not null, primary key (TRANSACTIONS_ID))
Hibernate: alter table APP.TRANSACTIONS add constraint
UK_r7btjtpy72nugbhuia8y0xnk6 unique (ITEM_ID)
Hibernate: alter table APP.ADVICENOTE add constraint
FK4n4r6ej5i983gk8fqj20jl899 foreign key (partner) references
APP.PARTNER
Hibernate: alter table APP.ADVICENOTE add constraint
FKr96drd4j6pds8vocvsstcd2a2 foreign key (PARTNER_ID) references
APP.PARTNER
Hibernate: alter table APP.ITEMS add constraint
FKbbkng91eiiqu522okqq0nq7pm foreign key (CATEGORY_ID) references
APP.CATEGORIES
Hibernate: alter table APP.TRANSACTIONS add constraint
FK13kk35nfl3iff7f2cs8er8w0s foreign key (advicenote) references
APP.ADVICENOTE
Hibernate: alter table APP.TRANSACTIONS add constraint
FK8ilbnqyk8lemxj0yvbqm3p7tt foreign key (ITEM_ID) references APP.ITEMS
Hibernate: alter table APP.TRANSACTIONS add constraint
FKqrbn7tojjjkjyusy98a300btp foreign key (ADVICENOTE_ID) references
APP.ADVICENOTE
Hibernate: select categories0_.NAME as col_0_0_ from APP.CATEGORIES
categories0_
Hibernate: select items0_.ITEM_ID as ITEM_ID1_2_, items0_.NAME as
NAME2_2_, items0_.NET_PRICE as NET_PRIC3_2_, items0_.VAT_RATE as
VAT_RATE4_2_, items0_.CATEGORY_ID as CATEGORY5_2_ from APP.ITEMS
items0_
Hibernate: select items0_.ITEM_ID as ITEM_ID1_2_, items0_.NAME as
NAME2_2_, items0_.NET_PRICE as NET_PRIC3_2_, items0_.VAT_RATE as
VAT_RATE4_2_, items0_.CATEGORY_ID as CATEGORY5_2_ from APP.ITEMS
items0_
Hibernate: select categories0_.NAME as col_0_0_ from APP.CATEGORIES
categories0_
Hibernate: select items0_.ITEM_ID as ITEM_ID1_2_, items0_.NAME as
NAME2_2_, items0_.NET_PRICE as NET_PRIC3_2_, items0_.VAT_RATE as
VAT_RATE4_2_, items0_.CATEGORY_ID as CATEGORY5_2_ from APP.ITEMS
items0_
Is this normal behaviour or am I missing something?
Here are my XML mappings:
Advicenote.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">
<!-- Generated Feb 9, 2019, 3:57:52 PM by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
<class name="classes.Advicenote" table="ADVICENOTE" schema="APP" optimistic-lock="version">
<id name="advicenoteId" type="int" column="ADVICENOTE_ID">
<generator class="native" />
</id>
<property name="advicedate" type="date" column="ADVICE_DATE" length="10" />
<property name="inOrOut" type="java.lang.Short" column="IN_OR_OUT" />
<many-to-one
name="partner" class="classes.Partner"/>
<set name="transactions" table="TRANSACTIONS" inverse="false" cascade="all" lazy="true" fetch="select">
<key column="ADVICENOTE_ID" not-null="true"/>
<one-to-many class="classes.Transactions"/>
</set>
</class>
</hibernate-mapping>
Categories.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 name="classes.Categories" table="CATEGORIES" schema="APP" optimistic-lock="version">
<id name="categoryId" type="int">
<column name="CATEGORY_ID" />
<generator class="native" />
</id>
<property name="name" type="string">
<column name="NAME" length="100" />
</property>
<set name="items" table="ITEMS" inverse="true" cascade="all" lazy="false" fetch="select">
<key>
<column name="CATEGORY_ID" not-null="true" />
</key>
<one-to-many class="classes.Items" />
</set>
</class>
</hibernate-mapping>
Items.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 name="classes.Items" table="ITEMS" schema="APP" optimistic-lock="version">
<id name="itemId" type="int" column="ITEM_ID">
<generator class="native" />
</id>
<property name="name" type="string" column="NAME" length="100"/>
<property name="netPrice" type="java.lang.Integer" column="NET_PRICE"/>
<property name="vatRate" type="java.lang.Integer" column="VAT_RATE"/>
<many-to-one name="category" class="classes.Categories" fetch="select" column="CATEGORY_ID" not-null="true" lazy="false"/>
</class>
</hibernate-mapping>
Limit.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 name="classes.Limit" table="LIMIT" schema="APP" optimistic-lock="version">
<id name="limitId" type="java.lang.Integer" column="LIMIT_ID">
<generator class="assigned"/>
</id>
<property name="value" type="int" column="LIMIT_VALUE" length="1000"/>
</class>
</hibernate-mapping>
Partner.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 name="classes.Partner" table="PARTNER" schema="APP">
<id name="partnerId" type="int">
<column name="PARTNER_ID"/>
<generator class="native"/>
</id>
<property name="partnerName" type="string" column="PARTNER_NAME" length="100"/>
<set name="advicenotes" table="ADVICENOTE" inverse="false" cascade="all" lazy="true" fetch="select">
<key column="PARTNER_ID" not-null="true"/>
<one-to-many class="classes.Advicenote" />
</set>
</class>
</hibernate-mapping>
Transactions.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 name="classes.Transactions" table="TRANSACTIONS" schema="APP" optimistic-lock="version">
<id name="transactionsId" type="int" column="TRANSACTIONS_ID">
<generator class="native" />
</id>
<property name="flow" type="int" column="FLOW" not-null="true" />
<property name="netPrice" type="java.lang.Integer" column="NET_PRICE" />
<many-to-one name="advicenote" class="classes.Advicenote"/>
<many-to-one name="item" class="classes.Items" fetch="select" cascade="save-update" column="ITEM_ID" unique="true" not-null="true"/>
</class>
</hibernate-mapping>
An AdviceNote mapping JoinColumn is missing
<many-to-one name="partner" class="classes.Partner">
<join-column name="PARTNER_ID"/>
</many-to-one>
I have been working for hours trying to solve this problem, which seems quite simple from a database point of view but hard to figure out with hibernate.
I have got two tables: VehicleCategory, and Vehicle.
A Vehicle has one VehicleCategory, so a Vehicule references a VehiculeCategory using a foreign key.
VehicleCategory:
String attr1
String attr2
Integer attr3
String attr4
PRIMARY KEY (attr1, attr2, attr3, attr4)
Vehicle
String name
String attr1
String attr2
Integer attr3
String attr4
FOREIGN KEY (attr1, attr2, attr3, attr4) REFERENCES VehicleCategory
PRIMARY KEY (name, attr1, attr2, attr3)
Here is my point: I do not want to use attr4 for my primary key, but I want to use the other foreign attributes in my primary key.
This is the mapping I did:
<class name="Vehicle" table="vehicle">
<composite-id>
<key-property name="name" column="name"/>
<key-many-to-one name="vehiclecategory" class="VehicleCategory">
<column name="attr1" not-null="true" />
<column name="attr2" not-null="true" />
<column name="attr3" not-null="true" />
</key-many-to-one>
</composite-id>
<many-to-one name="vehiclecategory" class="VehicleCategory" fetch="select" insert="false" update="false" >
<column name="attr1" not-null="true" />
<column name="attr2" not-null="true" />
<column name="attr3" not-null="true" />
<column name="attr4" not-null="true" />
</many-to-one>
</class>
I get the following exception:
Foreign key (FK_s94md9vv63hrpwhyaw4rfxec5:vehicle [attr1,attr2,attr3])) must have same number of columns as the referenced primary key (vehicle_category [attr4,attr1,attr2,attr3])
I understand what this exception means. But I do not see why I get it because, from my point of view, I did reference the 4-columns primary key in my foreign key, and only used 3 in my Vehicule primary key.
I am using Hibernate 4.3.6
Thank you for your help !
I have 2 tables:
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
address INT NOT NULL,
PRIMARY KEY (id)
);
create table ADDRESS (
id INT NOT NULL auto_increment,
street_name VARCHAR(40) default NULL,
city_name VARCHAR(40) default NULL,
state_name VARCHAR(40) default NULL,
zipcode VARCHAR(10) default NULL,
PRIMARY KEY (id)
);
where EMPLOYEE.address is a foreign key mapped to ADDRESS
My mapping file is defined as follows:
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<meta attribute="class-description">
This class contains the employee detail.
</meta>
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name" type="string"/>
<property name="lastName" column="last_name" type="string"/>
<property name="salary" column="salary" type="int"/>
<many-to-one name="address" column="address" unique="true"
class="Address" not-null="true"/>
</class>
<class name="Address" table="ADDRESS">
<meta attribute="class-description">
This class contains the address detail.
</meta>
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="street" column="street_name" type="string"/>
<property name="city" column="city_name" type="string"/>
<property name="state" column="state_name" type="string"/>
<property name="zipcode" column="zipcode" type="string"/>
</class>
</hibernate-mapping>
But, when I pull Employee objects all the normal fields are populated normally except the Address field in the Employee plain old object has all the values set to null. What could be causing this?
Unfortunately a bit long for a comment, but hopefully this will give you something to look at:
It is my understanding that NHibernate is actually "lazy by default", this means that the Address object won't be populated until requested, and then (if I remember correctly) only if you are still connected. I've had issues in the past of passing partially loaded objects to a view in my MVC projects and yours sounds similar.
That being said, I've read on several articles that you NHibernate doesn't lazy-load for many-to-one relationships, however I still think this is probably worth looking into. The many-to-one relationship requires the use of a foreign key, and therefore the referencing column must be the primary key. I.e. EMPLOYEE.address = ADDRESS.id.
Once you solve your problem please post what was actually wrong as I am looking to improve my knowledge in NHibernate.
You might find the following articles useful:
Solving Performance Problems with nHibernate (or any ORM)
And these Questions:
NHibernate: many-to-one and lazy
NHibernate 1.x : many-to-one not lazily loaded
I need to map a single class to two tables (both with multiple columns primary key). Let's say TABLE1 has id1, id2, id3 and TABLE2 has id1, id2 as primary keys. Now when writing the mapping file I would do something like the following:
<hibernate-mapping package="beans">
<class name="TABLE1Class" table="TABLE1">
<composite-id name="table1PK" class="TABLE1PKClass">
<key-many-to-one name="id1" class="ID1Class" column="id1"/>
<key-many-to-one name="id2" class="ID2Class" column="id2"/>
<key-many-to-one name="id3" class="ID3Class" column="id3"/>
</composite-id>
<property name="someProperty" type="integer" not-null="true" column="x"/>
<join table="TABLE2">
<key column="id1" />
<!-- <key column="id2"/> The join tag accepts only one key tag!!!
How do I map the second key??? -->
<property name="propertyFromTable2" type="float" not-null="true"/>
</join>
</class>
</hibernate-mapping>
As you can see the join tag accepts only one key tag! How do I map the second Id?
<key> may contain multiple <column> elements:
<key>
<column name = "id1" />
<column name = "id2" />
<column name = "id3" />
</key>
I am fairly a newbie with hibernate but I have been using Netbeans and hibernate reverse engineering tool to generate POJOs from an existing schema. All the POJOs for each table are created just fine except for join tables which i believe it is supposed to be this way as I can see the associations are being created in the mapping files. But the problem comes when I attempt to execute HBL query I get an exception that one of my join tables is not mapped. I know there is a mapping entry in config file, the only thing I could think of is that my data model is incorrect. I have a fairly large ER model but the problem tables are
I have User, Student, Major and StudentMajor tables. Below are my create statements
CREATE TABLE IF NOT EXISTS `Portfolio`.`User` (
`919Number` INT(11) NOT NULL ,
`loginId` VARCHAR(45) NOT NULL ,
`password` VARCHAR(8) NOT NULL ,
`userType` VARCHAR(10) NOT NULL ,
`lastName` VARCHAR(45) NULL DEFAULT NULL ,
`firstName` VARCHAR(45) NULL DEFAULT NULL ,
PRIMARY KEY (`919Number`) );
CREATE TABLE IF NOT EXISTS `Portfolio`.`Student` (
`919Number` INT(11) NOT NULL ,
`LEVL_CODE` VARCHAR(10) NOT NULL ,
PRIMARY KEY (`919Number`) ,
INDEX `919Number` (`919Number` ASC) ,
CONSTRAINT `919Number`
FOREIGN KEY (`919Number` )
REFERENCES `Portfolio`.`User` (`919Number` )
ON DELETE NO ACTION
ON UPDATE NO ACTION);
CREATE TABLE IF NOT EXISTS `Portfolio`.`Major` (
`majorCode` VARCHAR(10) NOT NULL ,
`majorDescription` VARCHAR(45) NULL DEFAULT NULL ,
PRIMARY KEY (`majorCode`) );
CREATE TABLE IF NOT EXISTS `Portfolio`.`StudentMajor` (
`919Number` INT(11) NOT NULL ,
`majorCode` VARCHAR(10) NOT NULL ,
PRIMARY KEY (`919Number`, `majorCode`) ,
INDEX `studentmajor_919Number` (`919Number` ASC) ,
INDEX `studentmajor_majorCode` (`majorCode` ASC) ,
CONSTRAINT `studentmajor_919Number`
FOREIGN KEY (`919Number` )
REFERENCES `Portfolio`.`Student` (`919Number` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `studentmajor_majorCode`
FOREIGN KEY (`majorCode` )
REFERENCES `Portfolio`.`Major` (`majorCode` )
ON DELETE NO ACTION
ON UPDATE NO ACTION);
Here is my hibernate config file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/portfolio</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">admin</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">jta</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</property>
<mapping resource="com/portfolio/hibernate/mappings/User.hbm.xml"/>
<mapping resource="com/portfolio/hibernate/mappings/Student.hbm.xml"/>
<mapping resource="com/portfolio/hibernate/mappings/Major.hbm.xml"/>
</session-factory>
</hibernate-configuration>
and I am using Netbeans hibernate POJO genereation tool. But when I run the queries I get the below exception:
org.hibernate.MappingException: An
association from the table
studentmajor refers to an unmapped
class:
com.portfolio.hibernate.mappings.Student
at
org.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:1252)
at
org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1170)
at
org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:324)
at
org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1286)
at
org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
Is there a possibility that this error is caused by the way I have modeled my tables? Any help will be appreciated.
As suggested I am including contents of the hbm.xml files for Student and Major.
Student:::
<hibernate-mapping>
<class name="com.jopos.Student" table="student" catalog="portfolio">
<id name="nineOneNumber" type="int">
<column name="nineOneNumber" />
<generator class="assigned" />
</id>
<many-to-one name="user" class="com.jopos.User" update="false" insert="false" fetch="select">
<column name="nineOneNumber" not-null="true" unique="true" />
</many-to-one>
<property name="levlCode" type="string">
<column name="LEVL_CODE" length="10" not-null="true" />
</property>
<set name="faculties" inverse="false" table="advises">
<key>
<column name="studentnineOneNumber" not-null="true" />
</key>
<many-to-many entity-name="com.jopos.Faculty">
<column name="facultynineOneNumber" not-null="true" />
</many-to-many>
</set>
<set name="majors" inverse="false" table="studentmajor">
<key>
<column name="nineOneNumber" not-null="true" />
</key>
<many-to-many entity-name="com.jopos.Major">
<column name="majorCode" length="10" not-null="true" />
</many-to-many>
</set>
<set name="enrolls" inverse="true">
<key>
<column name="nineOneNumber" not-null="true" />
</key>
<one-to-many class="com.jopos.Enroll" />
</set>
</class>
</hibernate-mapping>
Major:::
<hibernate-mapping>
<class name="com.jopos.Major" table="major" catalog="portfolio">
<id name="majorCode" type="string">
<column name="majorCode" length="10" />
<generator class="assigned" />
</id>
<property name="majorDescription" type="string">
<column name="majorDescription" length="45" />
</property>
<set name="students" inverse="true" table="studentmajor">
<key>
<column name="majorCode" length="10" not-null="true" />
</key>
<many-to-many entity-name="com.jopos.Student">
<column name="nineOneNumber" not-null="true" />
</many-to-many>
</set>
</class>
</hibernate-mapping>
We had similar problem. It was solved when we changed our MySql tables from MyISAM to InnoDB.
I hope it helps
Maxim
The Student class your exception is been refering to is fetched from:
com.portfolio.hibernate.mappings.Student
Your Student.hbm.xml holds Student in the package:
com.jopos.Student
Do resolve the reference issue. Make sure com.jopos.Major is refering to com.jopos.Student in its import. And also make sure table studentmajor and its mapping exist.