Hibernate mapping: creating FK relation in existing db for join operations - java

I have an existing db that I cannot alter. There are two tables, one (A) with a PK and one (B) with a FK pointing to the PK of the first. The respective columns are named (A).page_id and (B).cl_from.
In Hibernate mapping i can set an id for the first, mapping the PK. I can also set a bag for the one-to-many relationship.
For the second, I don't need an id, but a many-to-one relationship. How can you set a many-to-one relationship without an id? I don't want to insert an id to the class..
I've tried to set a composite key but had no luck..
// The PK class
<class name="Words" table="PAGE">
<id name="id" column="PAGE_ID" />
<property name="text" column="PAGE_TITLE" />
<bag cascade="all-delete-orphan" inverse="true" lazy="false" name="wordPages">
<key column="PAGE_ID"/>
<one-to-many class="CategoryItems"/>
</bag>
</class>
// The FK class
<class name="CategoryItems" table="CATEGORYLINKS" >
<composite-id>
<key-many-to-one name="id" column="CL_FROM" />
</composite-id>
<property name="text" column="CL_TO" />
</class>
And my classes:
public class Words {
private Long id;
private String text;
private ArrayList wordPages;
// getters - setters
public class CategoryItems implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Long id;
private String text;
//getters-setters
The latest error i get is: An association from the table CATEGORYLINKS refers to an unmapped class: java.lang.Long

should help with the following code:
public class CategoryItems implements Serializable
{
private static final long serialVersionUID = 1L;
private Words id;
private String text;
//getters-setters
}

Related

How to map detached Collection(List, Set) or Map with Hibernate via annotations

I know, that there is a way to map Map via XML:
<set name="images"
table="ITEM_IMAGE"
order-by="IMAGENAME asc">
<key column="ITEM_ID"/>
<composite-element class="Image">
<property name="name" column="IMAGENAME" not-null="true"/>
<property name="filename" column="FILENAME" not-null="true"/>
<property name="sizeX" column="SIZEX" not-null="true"/>
<property name="sizeY" column="SIZEY" not-null="true"/>
</composite-element>
</set>
Is there way to do the same thing via annotations mapping, and how to persist it into separate table?
Thatks a lot!
For composite values or basic types it should be almost the same, first you need to tell hibernate that we are mapping to a collection
then specify the name of the table which should hold your map and the join column with your current entity , then you specify the key.
#Entity
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Item_ID")
private Long itemId;
#ElementCollection
#CollectionTable(name="ITEM_IMAGE", joinColumns=#JoinColumn(name="ITEM_ID"))
#MapKeyColumn(name="ITEM_ID")
private Map<String, Image> contacts = new HashMap<String, Image>();
}
#Embeddable
public class Image {
//Specify your composite attributes with the column name for each
}
hope I did not miss anything

One object from two tables

I have two tables and want to map them to one object with Hibernate.
The reason for both tables is in the past and I wont change the frontend, which access data like this.
I have Table Event (Event_ID, Preview, img) and Event_Details (ID, Event_ID, content).
I prepare one class in Java:
public class Event {
private int event_ID;
private String preview;
private String img;
private String content;
//Getter and Setter
}
and following XML mapping file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 16.03.2016 20:33:10 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="de.data.events.Event" table="ev1_event">
<id name="id" type="int">
<column name="Event_ID" />
<generator class="assigned" />
</id>
<property name="preview" type="java.lang.String">
<column name="ev1_preview" />
</property>
<property name="img" type="java.lang.String">
<column name="ev1_img" />
</property>
</class>
<class name="de.data.events.Event" table="pb1_event">
<id name="id" type="int">
<column name="id" />
<generator class="assigned" />
</id>
//some properties
</class>
The part, where I have to join table1 to table2 is missing. But I didnĀ“t found a way to fix my problem.
First, you'd have your Hibernate entities. Yours are Event and EventDetail, but for fun, let's go with Person and Address in this example. The key here is that you need a one-to-one or many-to-one relationship between your tables. Otherwise, your resultset will come out weird (more on that later).
#Entity
#Table(name = "PERSON")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PERSON_ID")
public Integer id;
#Column(name = "NAME")
public String name;
#Column(name = "HOME_ADDRESS_ID")
public Integer homeAddressId;
#Column(name = "TEMP_ADDRESS_ID")
public Integer tempAddressId;
// . . . other fields,getters,setters
}
#Entity
#Table(name = "ADDRESS")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ADDRESS_ID")
public Integer id;
#Column(name = "STREET")
public String street;
#Column(name = "CITY")
public String city;
// . . . other fields,getters,setters
}
Then you'd have your target FlatObject POJO with the a constructor that will build it appropriately:
public class FlatObject {
public final String name;
public final String homeStreet;
public final String homeCity;
public final String tempStreet;
public final String tempCity;
public FlatEntity(String name, String homeStreet, String homeCity, String tempStreet, String tempCity) {
this.name = name;
this.homeStreet = homeStreet;
this.homeCity = homeCity;
this.tempStreet = tempStreet;
this.tempCity = tempCity;
}
// . . . other fields,getters
}
Finally, you'd leverage those objects with a Hibernate HQL SELECT where you join Person and Address and use their fields to construct a new FlatEntity:
SELECT new FlatEntity(p.name, ha.homeStreet, ha.homeCity, ta.tempStreet, ta.tempCity)
FROM
Person p, Address ha, Address ta
WHERE
p.homeAddressId = ha.id
and p.tempAddressId = ta.id
As you can see, the HQL statment will join Person to Address twice: once for the home address and once for the temp address.
The same will hold true in your case. So in your case, if you're joining Event e, EventDetail ed WHERE e.id = ed.eventId, just be sure there's only one detail row per Event. Otherwise you'll get multiple rows when you have more than one details or you'll drop rows (because of the inner join) when an event has no details.

Mapping Hibernate

I have 2 Entities: Technologie and Competence
Each competence can have 1 or more Techno
so i have generate the classes by Hibernate
and he gave me 3 classes Model
Technologie
Competence
TechnologieId
and now i'm confused about how to add a technologie
and what is the point of TechnoligieId ?
Technologie.java
public class Technologie implements java.io.Serializable {
private TechnologieId id;
private Competence competence;
private String libelleTechnologie;
}
TechnologieId.java
public class TechnologieId implements java.io.Serializable {
private int idCompetence;
private int idTechnologie;
}
Technologie.hbm.xml
<class name="com.model.Technologie" table="technologie" catalog="gestioncollaborateur">
<composite-id name="id" class="com.model.TechnologieId">
<key-property name="idCompetence" type="int">
<column name="idCompetence" />
</key-property>
<key-property name="idTechnologie" type="int">
<column name="idTechnologie" />
</key-property>
</composite-id>
<many-to-one name="competence" class="com.model.Competence" update="false" insert="false" fetch="select">
<column name="idCompetence" not-null="true" />
</many-to-one>
<property name="libelleTechnologie" type="string">
<column name="libelleTechnologie" length="254" />
</property>
</class>
If the relationship is mentioned correctly in the question. Then why dont you do something like this?
public class Technologie implements java.io.Serializable {
private id;
private Competence competence;
private String libelleTechnologie;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="<yourForeign Key for Competence>")
public Competence getCompetence() {
return competence;
}
}
And the Competence Class such as.
public class Competence implements java.io.Serializable {
private id;
private List<Technologie> technologies;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(mappedBy = "<name of the property of Competence in Technology class>")
public List<Technologies> getTechnologies() {
return technologies;
}
}
Also, this is if the Technology is the managing side of the relationship. Basically, what it means is you will do a save / update on the Technologie primarily which will handle the relationship.
If you do want the #OneToMany side as the managing side. you would have to add the insertable=false, updatable=false attributes in the #JoinColumn annotation for the the getTechnologies method.

Provided id of the wrong type hibernate

I am getting error:
org.hibernate.TypeMismatchException: Provided id of the wrong type for class BEntity. Expected: class BEntity, got class AEntity
public class BEntity implements Serializable{
#Id
#Column(name = "NUM")
private String num;
#Id
#Column(name = "INIT")
private String init;
#Column(name = "V_CNT")
private Integer vcnt;
//{{{some column omitted}}}//
}
public class AEntity implements Serializable{
#Id
#Column(name = "NUM")
private String num;
#Id
#Column(name = "INIT")
private String init;
#OneToOne
#PrimaryKeyJoinColumns({
#PrimaryKeyJoinColumn(name="NUM", referencedColumnName="NUM"),
#PrimaryKeyJoinColumn(name="INIT", referencedColumnName="INIT")
})
private BEntity bEntity;
}
HQL query:
String queryString = "FROM AEntity AS A " +
"LEFT JOIN A.bEntityAS B " +
"WHERE A.INIT||A.NUM IN (:carList) AND A.INIT IN (:initList) AND A.NUM IN (:numberList) " +
"AND B.TRUK_AXL_CNT > 0";
Hibernate gen-code
select aentity0_.NUMBER as NUMBER4_0_, aentity0_.INITIAL as INITIAL4_0_, bentity_p1_.NUMBER as NUMBER5_1_, bentity_p1_.INITIAL as INITIAL5_1_, aentity0_.V_CNT as VCNT3_4_0_, aentity0_.EIN as EIN4_0_, aentity0_.TYP as TYP5_4_0_, aentity0_.TRUK_CNT as TRUK6_4_0_, bentity_p1_.TRUK_AXL_CNT as TRUK3_5_1_ from USR.aentity aentity0_ left outer join USR.bentity_PRIMARY bentity_p1_ on aentity0_.NUMBER=bentity_p1_.NUMBER and aentity0_.INITIAL=bentity_p1_.INITIAL
where (aentity0_.INITIAL||aentity0_.NUMBER in (?,?,?))
and (aentity0_.INITIAL in (?,?,?))
and (aentity0_.NUMBER in (?, ?, ?))
and bentity_p1_.TRUK_AXL_CNT>0
When I run the code in SQL Explorer it works only running it in code cause the issue...
Looks like this is a defect in hibernate version 3.2.6 which is still not resolved. Came across this JIRA.
Having multiple #Id is supported by Hibernate but seems it fails under one to one mapping, suggested way of resolving this is to use single CompositeKey, which means you create a PK class
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
#Embeddable
public class PKClass implements Serializable {
#Column(name = "NUM")
private String num;
#Column(name = "INIT")
private String init;
//gettter setter here
}
then in your Entity use this as the ID
public class BEntity implements Serializable{
#Id
private PKClass pkClass = null;
#Column(name = "V_CNT")
private Integer vcnt;
//{{{some column omitted}}}//
}
public class AEntity implements Serializable{
#Id
private PKClass pkClass = null;
#OneToOne
#PrimaryKeyJoinColumns({
#PrimaryKeyJoinColumn(name="NUM", referencedColumnName="NUM"),
#PrimaryKeyJoinColumn(name="INIT", referencedColumnName="INIT")
})
private BEntity bEntity;
}
I faced the same issue. I had two separate PK classes that had the same fields. So I removed one PK and used only one in the owner and child entity. This solved the problem.
I had the same problem.
Started situation
Primary key on master table
<composite-id name="id" class="model.E1Id">
<key-property name="taxpayerId" type="int">
<column name="TaxpayerID" />
</key-property>
<key-property name="year" type="int">
<column name="Year" />
</key-property>
</composite-id>
Primary key on detail table
<composite-id name="id" class="model.E1dataFromTaxPayerFolderId">
<key-property name="tid" type="int">
<column name="tID" />
</key-property>
<key-property name="year" type="int">
<column name="Year" />
</key-property>
</composite-id>
After repair
I change the class of detail table composite-id and i set the class of primary table like this:
<composite-id name="id" class="model.E1Id">
<key-property name="tid" type="int">
<column name="tID" />
</key-property>
<key-property name="year" type="int">
<column name="Year" />
</key-property>
</composite-id>
After that is necessary (if you have different names) to add in your primarykey class (in my case E1Id) the property tid (with getter and setter methods)

Hibernate mapping multiple classes to one table using hbm.xml

I am fairly new to Hibernate and need some help with hibernate-mapping.
I have 4 different classes which I want to map into one table, of which the primary key consists of attributes from 2 different classes. At the same time, I want to map only selected attributes from each class into a local database. I wish to avoid JPA annotations and define the mapping style in a hbm.xml file instead. How do I do that?
Take the following example:
public class Tenant implements Serializable {
private final static long serialVersionUID = 1L;
protected List<Rack> rack;
protected String type;
//getters setters
}
public class Rack implements Serializable {
private final static long serialVersionUID = 1L;
protected List<Circuit> circuit;
protected String rackLabel;
protected Boolean excludes;
//getters setters
}
public class Circuit implements Serializable {
private final static long serialVersionUID = 1L;
protected List<CircuitReadings> circuitReadings;
protected String circuitNo;
protected Boolean excludes;
//getters setters
}
public class CircuitReadings
implements Serializable {
private final static long serialVersionUID = 1L;
protected String date;
protected String kva;
protected String current;
protected String kwh;
//getters setters
}
And the eventual table should consist of the following:
type | rackLabel | circuitNo | date | kva | current | energy
"circuitNo" and "date" above should form the composite primary keys.
Can someone show me an example of how I should map this? Thanks!
Hibernate provide a way to map subclass using discriminator keyword.
<class name="Payment" table="PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="native"/>
</id>
<discriminator column="PAYMENT_TYPE" type="string"/>
<property name="amount" column="AMOUNT"/>
...
<subclass name="CreditCardPayment" discriminator-value="CREDIT">
<join table="CREDIT_PAYMENT">
<key column="PAYMENT_ID"/>
<property name="creditCardType" column="CCTYPE"/>
...
</join>
</subclass>
<subclass name="CashPayment" discriminator-value="CASH">
<join table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
...
</join>
</subclass>
<subclass name="ChequePayment" discriminator-value="CHEQUE">
<join table="CHEQUE_PAYMENT" fetch="select">
<key column="PAYMENT_ID"/>
...
</join>
</subclass>
</class>
There's nothing stopping you from doing that . Create 4 HBMs pointing to the same table but different Pojos . Though it can be done , as #Ioan Alexandru Cucu , it is not recommended .
<!-- HBM1-->
<class name="com.myProject.Rack"
table="My_Table">
<!-- HBM2-->
<class name="com.myProject.Rack"
table="My_Table">

Categories

Resources