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.
Related
I'm trying to achieve lazy load on the following.
User.java
public class User {
private int id;
private String userName;
private String password;
private Employee employee;
//getter and setters
}
User.hbm.xml
<hibernate-mapping>
<class name="com.site.dto.User" table="user">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="userName" type="string" update="false">
<column name="user_name" length="50" not-null="true" unique="true" />
</property>
<property name="password" type="string">
<column name="password" length="50" not-null="true" unique="true" />
</property>
<one-to-one name="employee" class="com.site.dto.Employee" fetch="select" cascade="save-update" />
</class>
</hibernate-mapping>
Employee.java
public class Employee implements Serializable{
private int id;
private String name;
private String email;
private User user;
// getter and setters
}
Employee.hbm.xml
<hibernate-mapping>
<class name="com.site.dto.Employee" table="employee">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="name" length="50" not-null="true" unique="true" />
</property>
<property name="email" type="string" update="false">
<column name="email" length="50" not-null="true" unique="true" />
</property>
// enforcing many-to-one to one-to-one by putting unique="true"
<many-to-one name="user" column="user_id" class="com.site.dto.User" unique="true" not-null="true" fetch="select" cascade="save-update" />
</class>
</hibernate-mapping>
First I'm getting the User Object based on username. Now I'm trying to load the employee object which gives me null pointer exception. So after digging on some debug, it seems to be using a select statement with wrong where clause. Here is the hibernate debug
select employee0_.id as id1_1_0_, employee0_.name as name2_1_0_, employee0_.email as email3_1_0_,employee0_.user_id as user_id25_1_0_, from employee employee0_ where employee0_.id=?
Why is the where clause is based on employee.id and not employee.user.id ? I think this is due to the reason on how one-to-one mapping works in hbm.xml configuration where one-to-one will be linked to child table's primary key id but not user_id. I'm forcing the many-to-one to one-to-one in employee by using unique="true". I can fetch the employee in Hibernate annotation's one-to-one by defining #Join-column but I can't figure out how to map the one-to-one in hbm.xml which should refer the child's user_id.
Figured out the solution a while back, but forget to post it.
The above problem is coz, by default one-to-one mapping will be implemented for a child table which have the parent's primary key as the Child's primary key. So if we're going to eliminate that default property and use one-to-one with many-to-one (unique=true), we should define property-ref
I've added property-ref in one-to-one mapping in User.hbm.xml and now it works fine.
<one-to-one name="employee" property-ref="user" class="com.site.dto.Employee" fetch="select" cascade="save-update" />
I am following Hibernate Documentation and trying to implement the example given for section 9.4. Components as composite identifiers but facing issues on how to implement it.
Here is what I have done:
My entity classes:
Order.java
public class Order {
private int id;
private Set<OrderLine> lines = new HashSet<OrderLine>();
// Setters & Getters
}
OrderLine.java
public class OrderLine {
private OrderLineId id;
private String name;
private Order order;
// Setters & Getters
}
OrderLineId.java
public class OrderLineId implements Serializable{
private int lineId;
private int orderId;
private int customerId;
// Setters & Getters
}
My mapping file which is having issues:
<hibernate-mapping>
<class name="Order" table="TEST_Order">
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<set name="lines" cascade="all">
<key column="orderId"/>
<one-to-many class="OrderLine"/>
</set>
</class>
<class name="OrderLine" table="TEST_OrderLine">
<composite-id name="id" class="OrderLineId">
<key-property name="lineId"/>
<key-property name="orderId"/>
<key-property name="customerId"/>
</composite-id>
<property name="name"/>
<many-to-one name="order" class="Order"
insert="false" update="false">
<column name="orderId"/>
<column name="customerId"/>
</many-to-one>
</class>
</hibernate-mapping>
When I am trying to create a session factory which parses this mapping file, I am getting an exception saying:
Caused by: org.hibernate.MappingException: Foreign key (FK_89b4nqt5l2n6tfd1d5tq0ill0:TEST_OrderLine [orderId,customerId])) must have same number of columns as the referenced primary key (TEST_Order [id])
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:110)
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:93)
at org.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:1816)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1739)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
Can someone please help me how to implement the example given in the documentation.
The OrderLine needs to reference the Order PK, which is not a composite key.
It means the many-to-one must be:
<many-to-one name="order" class="Order"
insert="false" update="false">
<column name="orderId"/>
</many-to-one>
The orderId is the FK to Order.id.
Then the one-to-many side will become:
<set name="lines" cascade="all">
<key>
<column name="orderId"/>
</key>
<one-to-many class="OrderLine"/>
</set>
So even if the OrderLine has a composite-key, the reference is made after Order.id, which is a simple key.
If you want to map other association to OrderLine, like OrderLineProduct then you'll need to use the composite-key to map the association between the parent (OrderLine) and the child (OrderLineProduct), so that OrderLineProduct has a composite-foreign-key back to OrderLine.
In both the table hbm mapping you should have same no. of column ,what you are using to make composite.You need to add these 3 column in TEST_Oder.
Example to follow :
<many-to-one name="orderLine" class="OrderLine">
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</many-to-one>
Refer same URL
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>
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;
[...]
}
So I got a new error and I narrowed it down to 2 classes. I think the mapping for the Map attribute of the "Grouping" class must be wrong. Here is the code:
Java Entities
public class Grouping {
private long id;
private Map<Meal, List<Integer>> mealsCounter;
}
public class Meal implements java.io.Serializable {
private long id;
private Grouping grouping;
}
Hibernate configuration
<hibernate-mapping>
<class name="data.Grouping" table="GROUPING">
<id name="id" type="long">
<column name="ID" />
<generator class="identity" />
</id>
<map name="mealsCounter" table="MEAL" lazy="true" access="field">
<key>
<column name="ID" />
</key>
<map-key type="data.Meal"></map-key>
<one-to-many class="data.Meal" />
</map>
</class>
<class name="data.Meal" table="MEAL">
<id name="id" type="long">
<column name="ID" />
<generator class="assigned" />
</id>
<many-to-one name="grouping" class="data.Grouping" fetch="join">
<column name="GROUPING" />
</many-to-one>
</class>
</hibernate-mapping>
When I try to persist and object I get the following errorlog:
Hibernate: insert into MEAL (NAME, GROUPING, ID) values (?, ?, ?)
756 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: -177, SQLState: 23503
756 [main] ERROR org.hibernate.util.JDBCExceptionReporter - integrity constraint violation: foreign key no parent; FK240BC3E3481002 table: MEAL