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.
Related
The error I get is " org.hibernate.MappingException: Repeated column in mapping for entity: cdd.model.Answer column: answer_id (should be mapped with insert="false" update="false") ". However when I put those as attributes I get the error: "Attribute "insert" must be declared for element type "id"."
Any help would be appreciated.
Class:
public class Answer {
UUID answerID;
String content;
//constructors and getters and setters
}
Table:
CREATE TABLE IF NOT EXISTS answer (
answer_id uuid NOT NULL ,
content text NOT NULL,
primary key(answer_id)
);
Hibernate Mapping File:
<!-->==== Answer ====<!-->
<class name="cdd.model.Answer" table="answer" >
<id column="answer_id" name="answerID"
type="org.hibernate.type.PostgresUUIDType"
insert="false" update="false">
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
<property column="content" name="content" type="org.hibernate.type.TextType"/>
</class>
Note
I have a Question class where a question has a set of answers. This is the mapping I used. I am posting it because the error I'm gettng may be because of how I mapped this one-to-many relationship (I'm not sure).
<!-- ==== Question ==== -->
<class name="cdd.model.Question" table="question">
<id column="question_id" name="questionID" type="org.hibernate.type.PostgresUUIDType">
< generator class="org.hibernate.id.UUIDGenerator"/>
</id>
<many-to-one column="submitted_by" name="submittedBy" not-null="true"/>
<many-to-one column="parentCategory" name="parentCategory" not-null="true"/>
<property column="title" name="title" type="org.hibernate.type.TextType"/>
<property column="correct_answer" name="correctAnswer" type="org.hibernate.type.TextType"/>
<property column="date_submitted" name="dateSubmitted" type="org.hibernate.type.TimestampType"/>
<set cascade="all" name="answers" table="answer">
<key column="answer_id" not-null="true"/>
<one-to-many class="cdd.model.Answer"/>
</set>
<join inverse="true" optional="true" table="category_questions">
<key column="question_id"/>
</join>
<join inverse="true" optional="true" table="accepted_questions_by_user">
<key column="question_id"/>
</join>
</class>
Question Entity:
<id column="question_id" name="questionID" type="org.hibernate.type.PostgresUUIDType">
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
Answer Entity:
<id column="answer_id" name="answerID" type="org.hibernate.type.PostgresUUIDType"
insert="false" update="false">
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
remove insert="false" update="false" from Answr entity
should look someting like this
<id column="answer_id" name="answerID" type="org.hibernate.type.PostgresUUIDType" >
<generator class="org.hibernate.id.UUIDGenerator"/>
</id>
update, insert (optional - defaults to true): specifies that the mapped columns should be included in SQL UPDATE and/or INSERT statements. Setting both to false allows a pure "derived" property whose value is initialized from some other property that maps to the same column(s), or by a trigger or other application.
I do not understand how to define a composite key, including one foreign key, inside of a set
Here my Objects:
MyObject MySubset
-------- -------------
String myId String subAttribute
String myAttribute String subValue
Set<MySubset> mySubset
I want to have two tables MyObjectTable and MySubsetTable.myId is primary key of MyObjectTable. I would like to define the FK myId and subAttribute as the composite keys of MySubsetTable.
What would the hibernate mapping of in xml look like?
<hibernate-mapping>
<class table="myObjectTable" name="MyObject">
<id name="myId">
<column name="myId"/>
</id>
<property name="myAttribute"> <column name=....> </property>
<set cascade="all, delete-orphan table="MySubsetTable" name"mySubset" ...>
<!-- How should I define my key? -->
<composite-element class="MySubset">
<property name="subAttribute"> <column name="subAttribute"/> </property>
<property name="subValue"> <column name="subValue"/> </property>
</composite-element>
</set>
</class>
</hibernate-mapping>
I solved my problem by not using a set, but a map:
<hibernate-mapping>
<class table="myObjectTable" name="MyObject">
<id name="myId">
<column name="myId"/>
</id>
<property name="myAttribute"> <column name=....> </property>
<map cascade="all, delete-orphan table="MySubsetTable" name"mySubset" ...>
<key not-null="true" foreign-key="FK_MyObj" column="MyObject"/>
<map-key type="string" column="myAttribute"/>
<element type="string" column="myValue"/>
</map>
</class>
</hibernate-mapping>
Maybe this helps someone else...
I have some simple code that is supposed to select all teacher objects from a table of teachers in my mysql database. When I run similar queries for other domain objects, it is extremely fast, but for some reason this query takes forever. Also if I run a select all query from mysql workbench it executes instantly, so I think the problem is with my hibernate mapping. There are only 30 ish entries in the table so there is no reason this should be taking long.
Hibernate mapping xml file:
<hibernate-mapping>
<class name="org.myschool.domain.Teacher" table="teacher">
<id name="teacher_id" type="java.lang.Integer">
<column name="teacher_id" />
<generator class="increment" />
</id>
<property name="firstName" type="java.lang.String">
<column name="first_name" length="20" not-null="true"/>
</property>
<property name="lastName" type="java.lang.String">
<column name="last_name" length="30" not-null="true" />
</property>
<property name="middleInitial" type="java.lang.String">
<column name="middle_initial" length="1" not-null = "false"/>
</property>
<set name="wantsCourses" table="teacher_want" inverse="false" lazy="true" fetch="select" cascade="all">
<key>
<column name="teacher_id" not-null="true" />
</key>
<many-to-many entity-name="org.myschool.domain.Course">
<column name="course_id" not-null="true" />
</many-to-many>
</set>
<set name="eligibleCourses" table="teacher_eligible" inverse="false" lazy="true" fetch="select" cascade="all">
<key>
<column name="teacher_id" not-null="true" />
</key>
<many-to-many entity-name="org.myschool.domain.Course">
<column name="course_id" not-null="true" />
</many-to-many>
</set>
<set name="teacherTranscript" table="assigned_course" inverse="true" lazy="true" fetch="select">
<key>
<column name="teacher_id" not-null="true" />
</key>
<one-to-many class="org.myschool.domain.AssignedCourse" />
</set>
</class>
</hibernate-mapping>
This is the method being called that takes so long :
public List<Teacher> findAll() {
try {
#SuppressWarnings("unchecked")
List<Teacher> results = (List<Teacher>) sessionFactory.getCurrentSession()
.createCriteria("org.myschool.domain.Teacher").list();
log.debug("find all successful, result size: " + results.size());
return results;
} catch (RuntimeException re) {
log.error("find all failed", re);
throw re;
}
}
And this is the actual hibernate query being executed:
Hibernate: select this_.teacher_id as teacher_1_8_0_, this_.first_name as first_na2_8_0_, this_.last_name as last_nam3_8_0_, this_.middle_initial as middle_i4_8_0_ from teacher this_
Here's the sql command that makes the teacher table:
CREATE TABLE teacher(
teacher_id INT(6) UNSIGNED NOT NULL PRIMARY KEY,
first_name VARCHAR(20) NOT NULL,
middle_initial CHAR(1),
last_name VARCHAR(30) NOT NULL)
Thanks for your help!
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.
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>