need an Hibernate ORM mapping idea - java

I Have a table(student) with columns stu_id, stu_name, favourite_subject, subject_id
favourite_subject will have predefined values like maths,english etc.
if the value is maths, subject_id will have table: maths_subject's id.
meaning, based on favourite_subject value, subject_id will be pointing to the corresponding subject's id.
How can i implement in Hibernate ORM Framework.
<hibernate-mapping package="com.sample.project">
<class name="StudentDTO" table="student">
<meta attribute="class-description">class to hold student data</meta>
<id name="id" type="long" column="stu_id">
<generator class="increment"/>
</id>
<discriminator column="favourite_subject" type="string"/>
<property name="studentName" column="stu_name" not-null="true"/>
<!--?? here i don't know how to proceed. ??-->
<subclass name="??????" discriminator-value="Maths">
????
</subclass>
</class>
</hibernate-mapping>
all subjects will have their own tables & own corresponding entity classes.

assuming following class structure
class Student
{
private Subject favoriteSubject;
}
class MathSubject : Subject
{
}
class EnglishSubject : Subject
{
}
corresponding mapping
<hibernate-mapping package="com.sample.project">
<class name="Student" table="student">
<meta attribute="class-description">class to hold student data</meta>
<id name="id" type="long" column="stu_id">
<generator class="increment"/>
</id>
<property name="studentName" column="stu_name" not-null="true"/>
<any name="subject" id-type="Integer" meta-type="String" cascade="all">
<meta-value value="math" class="MathSubject"/>
<meta-value value="english" class="EnglishSubject"/>
<column name="favourite_subject"/>
<column name="subject_id"/>
</any>
</class>
</hibernate-mapping>

Related

Hibernate XML - composite-id with one-to-one mapping

I cannot get it to work. The error says Broken column mapping. It has to be one-sided one-to-one mapping. Only 1 part of composite-id is connected to the other entity. Channel gonna be inserted based on logged user's access channel. I do have 2 classes.
public class UserModel implements Serializable{
private final Long id;
private final UserLimitsModel userLimitsModel;
}
public class UserLimitsModel implements Serializable{
private final Long userId;
private final String channel;
}
Then 2 hibernate .xml mappings
<hibernate-mapping>
<class name="abcdefgh.UserLimitsModel" table="USER_LIMITS" lazy="false">
<composite-id>
<key-property name="userId" type="long">
<column name="USER_ID" not-null="true"/>
</key-property>
<key-property name="channel" type="string" length="20">
<column name="CHANNEL" not-null="true"/>
</key-property>
</composite-id>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="abcdefgh.UserModel" table="USER" lazy="false">
<id name="id" type="long">
<column name="ID" precision="19" scale="0" />
<generator class="sequence">
<param name="sequence_name">ID_SEQ</param>
</generator>
</id>
<one-to-one name="userLimitsModel" class="abcdefgh.UserLimitsModel" cascade="all"/>
</class>
</hibernate-mapping>
So the only connection is UserModel.id = UserLimitsModel.userId, while channel stays separate.
Hi the problem is that you are not joining with the primary key. Also the column name in UserModel is ID and in UserLimitsModel is USER_ID. You need to tell hibernate how to perform the join
you can do this by defining property-ref on the one-to-one element.
<one-to-one name="userLimitsModel" class="abcdefgh.UserLimitsModel" property-ref="userId" cascade="all"/>
property-ref (optional): the name of a property of the associated
class that is joined to the primary key of this class. If not
specified, the primary key of the associated class is used.

Java Hibernate Mapping File not working

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.

How to initialize one more property in composite id

Have the following:
<class name="ClassName" entity-name="EntityName1" table="table1" lazy="false">
<composite-id name="classPK" class="com.....ClassPK">
<key-property name="ID" column="id" type="integer"/>
</composite-id>
.....
and
<class name="ClassName" entity-name="EntityName2" table="table2" lazy="false">
<composite-id name="classPK" class="com.....ClassPK">
<key-property name="ID" column="id" type="integer"/>
</composite-id>
.....
i.e. 2 entities that maps to 2 tables but with the same class. Composite ID is used like im code above. What is need it to initialize one more property in ClassPK class when entity EntityName2 or EntityName1 is loaded from DB. I need to initialize it by 2 different constant values. For example "value1" and value2 for EntityName1 and EntityName2 respectivly.
So I would like to have a possibility ti write something like
<class name="ClassName" entity-name="EntityName1" table="table" lazy="false">
<composite-id name="classPK" class="com.....ClassPK">
<key-property name="ID" column="id" type="integer"/>
<property name="propertyname" formula = "'value1'"/>
</composite-id>
Does anybody have an idea how to do this?
not sure if this is a good idea altogether but you coud try
<key-property name="propertyname" formula = "'value1'">
<column formula="'value1'"/>
</key-property>

how do I add one to many relationship in hibernate?

On the database, I have these two tables:
- Destination:
- idDestination
- name
- Airport:
- idAirport
- idDestination // FK into Destination city
- name
where:
1 Destination(read: city) has many Airports
1 Airport belongs to 1 City
Hence: 1-Many relation between Destination-Airports
My Java classes look like this:
class Destination{
private Integer idDestination;
private String name;
// getter and setters
}
class Airport{
private Integer idAirport;
private Destination city;
private String name;
}
// Separate class for airports in city, since city is being used in a lot of other places
// and I'd like to keep Destination class clean
class CityAirports{
private Destination City;
private Set<Airport> airports;
}
Hibernate Mappings: Airport.hbm.xml
<hibernate-mapping>
<class name="org.wah.dao.Airport" table="AIRPORT">
<id name="idAirport" type="java.lang.Integer">
<column name="IDAIRPORT" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<many-to-one name="city" class="org.wah.dao.Destination">
<column name="IDCITY" />
</many-to-one>
</class>
</hibernate-mapping>
I need to define another mapping for CityAirports to
- retrieve all the airports within the city.
- add a new airport to the city.
I am not sure what the hibernate mapping would look like ? Can someone please guide me on how to do it?
for destination mapping,
<hibernate-mapping>
<class name="org.wah.dao.Destination" table="DESTINATION">
<id name="idDestination" type="int" column="DESTINATION_ID">
<generator class="native" />
</id>
<property name="name" type="string" not-null="true" length="100"
column=DESTINATION_NAME" />
<set name="destinationAirPorts" table="DESTINATION_AIRPORT" cascade="all">
<key column="DESTINATION_ID" />
<many-to-many column="IDAIRPORT" unique="true" class="org.wah.dao.Airport" />
</set>
</class>
for airport mapping,
<hibernate-mapping>
<class name="org.wah.dao.Airport" table="AIRPORT">
<id name="idAirport" type="int" column="IDAIRPORT">
<generator class="native" />
</id>
<property name="name" type="string" not-null="true" length="100"
column=NAME" />
</class>
</hibernate-mapping>
Read the example mentioned here which describes the solution you are looking for neatly.
Basic idea is that you use many-to-many relationship from city-to-airport and place unique constraint on IDAIRPORT
Could be something like this ??
<class name="org.wah.dao.CityAirports">
<id name="caID">
<generator class="assigned" />
</id>
<set name="Airport" cascade="save-update" >
<key column="apID" />
<one-to-many class="org.wah.dao.Airport" />
</set>
<many-to-one name="city" class="org.wah.dao.Destination">
<column name="IDCITY" />
</many-to-one>
</class>
Is the CityAirport class really necessary? Why not just put a list of Airports into your Destination?
Not sure about the .xml configuration for this. But using annotations, you would get something like this:
#Entity
public class Destination {
#Id
#GeneratedValue
private Integer idDestination;
private String name;
#OneToMany(mappedBy="destination")
Set<Airport> airports;
[...]
}
And the Airport class:
#Entity
public class Airport {
#Id
#GeneratedValue
private Integer id;
#ManyToOne
private Destination destination;
[...]
}

hibernate one-to-one or component?

I am wondering how to write the model, hbm.xml for table
Company
-------
id(PK)
name
address
typeid(fk)
Type
----
id(PK)
type
class Company(){
int id;
String name;
String address;
Type type;
}
class Type(){
int id;
String type;
}
(with get/set methods)
How to write the hbm?
I am using the hibernate 3.x.
Can you have multiple companies of the same type?
Don't you really want a many to one relationship?
How about something like this (adapted from the Hibernate docs from here):
<class name="Company" table="company">
<id name="id" column="id">
...
</id>
....
<many-to-one name="type"
class="Type"
column="typeid"
not-null="true"/>
</class>
<class name="Type">
<id name="id" column="id">
...
</id>
</class>
the given situation is a many-to-one situation, because 1 type can be assigned to multiple companies
<class name="Company" table="company">
<id name="id" column="id">
<generator class="foreign">
<param name="property">type</param>
</generator>
</id>
...
<one-to-one name="type"
class="Type"
constrained="true"/>
</class>
More details here.
It's not obvious, but it's straight forward mapped with many-to-one.
<class name="Company" table="company">
<id name="id">
<generator class="native">
<param name="sequence">Company_SEQ</param>
</generator>
</id>
...
<many-to-one
name="type"
class="Type"
constrained="true"/>
</class>

Categories