Hibernate 1-to-1 mapping column is not being set - java

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

Related

Hibernate: foreign key partially used as primary key

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 !

hibernate how to select the many-side from an one-to-many relation

everyone. I'm brand new using Hibernate.
So here I face a question, I have an entity like below:
<class name="cn.edu.scau.librarica.dao.MessageSession" table="msg_session">
<id name="msid" type="long" unsaved-value="null">
<generator class="identity"/>
</id>
<list name="msgs" cascade="all">
<key column="msid"
update="false" unique="true" not-null="true"/>
<list-index column="list_index"/>
<one-to-many class="Message" />
</list>
</class>
And now what I want to achieve is:
select Message m where msid=# and m.t<## and m.t>###
How can I represent it with Criteria?
Thank you for your attentions and advices, in advance.
UPDATE
As one of the answer guide, I have got the point that composite-element is not queryable, so I made a both-sid one-to-many map(changed are above)
And now I can query but now I found another problem:
How can I mapped the composite-id with foreign-key
Message are map like this:
<class name="Message">
<composite-id>
<generator class="foreign">
<!-- What here??? -->
</generator>
</composite-id>
</class>
As instructed, one-to-many may use set rather than list, so I can hardly find sample meets my need(due to Message should be ordered).
Any advice? I am still searching for that.
Thanks for help.
You can't directly select the Message as it is a component and not an entity. Components don't have an independent life cycle. They cannot be queried, created or deleted on their own, they always have to be accessed via the entity in which they are embedded (MessageSession in your case).
To make it into an Entity the table should have it's own primary key. In your case that doesn't seem to be so. You will need to change the schema so that the table corresponding to Message has a primary key and change the mapping to use one-to-many instead of composite-element.
If you can't do that you will have to query the MessageSession and get message out of it.
P.S: Hibernate is quite complex, I haven't see too many people being able to just pick it up along the way just trying things out. You are more likely to succeed if you spend some time studying the underlying concepts (which are more important than just mapping & querying).
here is the author of question.
After several days of research, I found the way to satisfied my require somehow.
Maping Message
<class name="cn.edu.scau.librarica.dao.Message" table="message">
<id name="id" type="long">
<generator class="identity" />
</id>
<many-to-one name="ms" class="cn.edu.scau.librarica.dao.MessageSession"
column="msid" not-null="true" insert="false" update="false" />
<property name="s" type="long" />
<property name="t" type="timestamp" />
<property name="m" type="string" />
</class>
Mapping MessageSession
<class name="cn.edu.scau.librarica.dao.MessageSession" table="msg_session">
<id name="msid" type="long" unsaved-value="null">
<generator class="identity"/>
</id>
<property name="latest" type="timestamp" />
<list name="msgs" table="msg_session_msgs" cascade="all">
<key column="msid"
update="false" not-null="true"/>
<list-index column="list_index"/>
<one-to-many class="cn.edu.scau.librarica.dao.Message" />
</list>
</class>
Among them, the unimportant are neglected.
Things go quite well while I can find the "one" with restrictions of "many" or inversely. just like this:
DetachedCriteria dc = DetachedCriteria.forClass(Message.class)
.createCriteria("ms")
.add(Restrictions.eq("msid", msid));
if (after != null)
dc.add(Restrictions.gt("t", after));
if (before != null)
dc.add(Restrictions.lt("t", before));
...can search out Message during the specified period from specified MessageSession.
So the trick is objects can't be returned by Criteria unless match them as entity.
On the underlaying database, it will be a little redundant, since Message can be uniquely identified by (msid,list_index), so I am finding a way to match <-this as the primary key for Message.

hibernate composite-id as a part other composite-id

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.

Hibernate: optional many-to-one with not-null columns

I've got an optional many-to-one relationship between two classes. Hibernate translates the property to be optional by setting the foreign keys to null.
My db-schema does not allow the columns to be null. The property to be optional is represented by the default-value of these columns.
<class name="sth.Alpha" ...>
....
<many-to-one name="beta" not-found="ignore" class="sth.Beta" insert="true" update="true">
<column name="a1/>
<column name="a2/>
</many-to-one>
</class>
<class name="sth.Alpha" ...>
<composite-id>
<key-property name="b1" type="int">
<column name="b1" precision="8" scale="0"/>
</key-property>
<key-property name="b2" type="int">
<column name="b2" precision="8" scale="0"/>
</key-property>
</composite-id>
</class>
selecting data is no problem because of not-found="ignore" in the may-to-one-tag it will result in a null-beta-object. But if I want to insert an Alpha? with beta set to null. I get an Exception, that it is not possible to insert null to a1 and a2.
I get rid of that problem if I set insert and update to false. But this results in not saving the relationship if it is set.
Database-Schema cannot be changed and Hibernate-version is fixed to 3.5
I would also be happy if you tell me, that it is not possible
how to use 0 instead of null in conjunction with <id unsavedvalue="whatever"> might help
or
other solution

Hibernate generated POJOs

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.

Categories