Read data from table where primary key is composite using hibernate - java

I have these POJO classes in my project.
public class MerchantChainUser extends com.avanza.ni.common.dto.AbstractDTO
implements java.io.Serializable {
private long chainId;
private CompositePK compositePK;
public MerchantChainUser() {
}
public void setChainId(long chainId) {
this.chainId = chainId;
}
public long getChainId() {
return chainId;
}
public void setCompositePK(CompositePK compositePK) {
this.compositePK = compositePK;
}
public CompositePK getCompositePK() {
return compositePK;
}
}
AND
public class CompositePK implements Serializable {
private long merchantId;
private long userId;
public void setMerchantId(long merchantId) {
this.merchantId = merchantId;
}
public long getMerchantId() {
return merchantId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public long getUserId() {
return userId;
}
}
hbm.xml file for MerchantUserChain is
<hibernate-mapping>
<class name="com.avanza.ni.portal.dto.MerchantChainUser" table="MERCHANT_CHAIN_USER">
<composite-id name="compositePK">
<key-property name="merchantId" type="long" column="MERCHANT_ID"></key-property>
<key-property name="userId" type="long" column="MERCHANT_USER_ID"></key-property>
</composite-id>
<property name="chainId" type="long">
<column name="MERCHANT_CHAIN_ID" length="38" />
</property>
</class>
Now what i wanted is i have to read data from the table using just MERCHANT_USER_ID. I am able to retreive whole data from the table but now i want to set a criteria as Only give me those row that MERCHANT_USER_ID is specific. I didn't know how to write data criteria.

the answer that i put the comment has been deleted, so i post it here :D
Criteria crit = session.createCriteria(MerchantChainUser.class)
.add(Restrictions.eq("compositePK.userId", userId));
or with hql
session.createQuery("from MerchantChainUser where compositePK.userId = :userid").setParameter("userid",userid);

Can you try:
Criteria crit = session.createCriteria(MerchantChainUser.class);
crit.add(Restrictions.eq("compositePK.merchantId", 42));
crit.add(Restrictions.eq("compositePK.userId", 43));
crit.setMaxResults(10);
List result = crit.list();
Vinit

Related

Hibernate returns the list of null

I am trying to use Hibernate but when I execute a query I receive a list of my entity where all the attributes are NULL. The thing is that when i use the jdbc directly I am able to retrieve the values from my Db.
I read similar articles about NULL values but couldn't figure out what s wrong in my case.
Below you see:
1) My entity: Eshop
public class Eshop implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public Eshop() {}
public Eshop(int eshopId, String code, String name, String lastModified) {
this.eshopId = eshopId;
this.code = code;
this.name = name;
this.lastModified = lastModified;
}
public int eshopId;
public String code;
public String name;
public String lastModified;
public int getEshopId() {
return eshopId;
}
public void setEshopId(int eshopId) {
eshopId = eshopId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
name = name;
}
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
lastModified = lastModified;
}
2) The Hibernate Mapping
<hibernate-mapping>
<class name="dataModel.Eshop" table="Eshop">
<meta attribute="class-description">
This class contains the Eshop details.
</meta>
<id name="eshopId" type="int" column="EshopId">
<generator class="native"/>
</id>
<property name="code" column="Code" type="string"/>
<property name="name" column="Name" type="string"/>
<property name="lastModified" column="LastModified" type="string"/>
</class>
</hibernate-mapping>
And this is how I run the query:
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query hibernateQuery = session.createQuery("from Eshop");
List<Eshop> Eshops = hibernateQuery.list();
So when I run a query i receive the exact number of Eshops which are in my Db but all their attributes values are null!!
An ideas?? Thank you
All your setters are wrong:
public void setEshopId(int eshopId) {
eshopId = eshopId;
}
This is a noop. It should be
public void setEshopId(int eshopId) {
this.eshopId = eshopId;
}
Try to add hibernate.cfg.xml like this:
Configuration config = new Configuration().configure("hibernate.cfg.xml");

hibernate dynamic component equivalent annotation

What is the equivalent way of defining dynamic component in hibernate by annotations?
public abstract class CustomizableEntity {
private Map customProperties;
public Map getCustomProperties() {
if (customProperties == null)
customProperties = new HashMap();
return customProperties;
}
public void setCustomProperties(Map customProperties) {
this.customProperties = customProperties;
}
public Object getValueOfCustomField(String name) {
return getCustomProperties().get(name);
}
public void setValueOfCustomField(String name, Object value) {
getCustomProperties().put(name, value);
}
}
my entity:
public class Contact extends CustomizableEntity {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
hibernate xml:
<hibernate-mapping auto-import="true" default-access="property" default-cascade="none" default-lazy="true">
<class abstract="false" name="com.enterra.customfieldsdemo.domain.Contact" table="tbl_contact">
<id column="fld_id" name="id">
<generator class="native"/>
</id>
<property name="name" column="fld_name" type="string"/>
<dynamic-component insert="true" name="customProperties" optimistic-lock="true" unique="false" update="true">
</dynamic-component>
</class>
</hibernate-mapping>
I want to use a dynamic-component by HashMap to create entities at runtime.
What is the equivalent way of defining dynamic component in hibernate by annotations?
http://www.infoq.com/articles/hibernate-custom-fields

Why am I getting org.hibernate.PropertyAccessException?

While trying to run the following program :
public class Runner {
public static void main(String args[]) {
Configuration config = new Configuration().configure();
SessionFactory sessFact = config.buildSessionFactory();
Session sess = sessFact.openSession();
Transaction trans = sess.beginTransaction();
Person p = new Person();
p.setPersonName("Suhail");
Set<String> set = new HashSet<String>();
set.add("Address-1");
set.add("Address-2");
set.add("Address-3");
p.setAddressSet(set);
sess.save(p);
trans.commit();
}
}
I am getting :
SEVERE: IllegalArgumentException in class: pojo.Address, getter method
of property: addressID
Exception in thread "main" org.hibernate.PropertyAccessException:
IllegalArgumentException occurred calling getter of pojo.Address.addressID
I don't know the reason for this. I am trying to make one to many association between Person and Address class.
mapping xml:
<hibernate-mapping>
<class name="pojo.Person" table="person">
<id name="personID" column="p_id">
<generator class="increment" />
</id>
<property name="personName" column="p_name" />
<set name="addressSet" table="address" cascade="all">
<key column="p_id" />
<one-to-many class="pojo.Address" />
</set>
</class>
<class name="pojo.Address" table="address">
<id name="addressID" column="a_id">
<generator class="increment" />
</id>
<property name="personAddress" column="p_address" />
</class>
</hibernate-mapping>
POJO:
Person
public class Person {
private int personID;
private String personName;
private Set addressSet;
public int getPersonID() {
return personID;
}
public void setPersonID(int personID) {
this.personID = personID;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public Set getAddressSet() {
return addressSet;
}
public void setAddressSet(Set addressSet) {
this.addressSet = addressSet;
}
}
Address
public class Address {
private int addressID;
private String personAddress;
public int getAddressID() {
return addressID;
}
public void setAddressID(int addressID) {
this.addressID = addressID;
}
public String getPersonAddress() {
return personAddress;
}
public void setPersonAddress(String personAddress) {
this.personAddress = personAddress;
}
}
SQL that created table
CREATE TABLE person(p_id INTEGER,p_name TEXT,PRIMARY KEY(p_id));
CREATE TABLE address(a_id INTEGER,p_address TEXT);
In your example you add to adress set Strings. But in your configuration you specify Address class.So I think your problem in this lines:
Set<String> set = new HashSet<String>();
set.add("Address-1");
set.add("Address-2");
set.add("Address-3");
You need to change set to Set<Address> and add Address objects in set:
Set<Address> set = new HashSet<>();
Address address = new Address();
address.setPersonAddress("Address-1");
set.add(address);
You can do couple of things without Mapping xml file. Place #Embeddable on ur Pojo of
#Embeddable
#Entity
public class Address {
#Id
private int addressID;
private String personAddress;
public int getAddressID() {
return addressID;
}
public void setAddressID(int addressID) {
this.addressID = addressID;
}
public String getPersonAddress() {
return personAddress;
}
public void setPersonAddress(String personAddress) {
this.personAddress = personAddress;
}
}
Then on
public class Runner {
public static void main(String args[]) {
Configuration config = new Configuration().configure();
SessionFactory sessFact = config.buildSessionFactory();
Session sess = sessFact.openSession();
Transaction trans = sess.beginTransaction();
Person p = new Person();
p.setPersonName("Suhail");
#ElementCollection//To inform hibernate to save this in a seperate table
Set<String> set = new HashSet<String>();
set.add("Address-1");
set.add("Address-2");
set.add("Address-3");
p.setAddressSet(set);
sess.save(p);
trans.commit();
}
}
Better to use Annotations so that we get rid of writing .hbm.xml mapping File

Hibernate mapping and query

The hibernate mapping of my hbm.xml is:
<class name="UserCalendar" table="user_calendar">
<id name="userCalendarId" column="user_calendar_id" type="long">
<generator class="native" />
</id>
<property name="userId" column="user_id" type="long" not-null="true"/>
<property name="userLoginName" column="user_login_name" type="string" not-null="true" length="32000" />
<property name="userName" column="user_name" type="string" not-null="true" length="32000" />
<list name="userDates" cascade="all" lazy="false">
<key column="user_calendar_id"/>
<index column="idx"/>
<one-to-many class="UserDate"/>
</list>
</class>
<class name="UserDate" table="user_date">
<id name="userDateId" column="user_date_id" type="long">
<generator class="native" />
</id>
<property name="date" column="date" type="date"/>
<list name="userItems" cascade="all" lazy="false">
<key column="user_date_id"/>
<index column="idx"/>
<one-to-many class="UserItem"/>
</list>
</class>
<class name="UserItem" table="user_item">
<id name="userItemId" column="user_item_id" type="long">
<generator class="native"/>
</id>
<property name="spaceId" column="space_id" type="long"/>
<property name="spaceName" column="space_name" type="string"/>
<property name="itemRefId" column="item_ref_id" type="string"/>
<property name="itemId" column="item_id" type="long"/>
<property name="allocation" column="allocation" type="double"/>
<property name="scheduledStrategy" column="scheduled_strategy" type="integer"/>
<property name="utilization" column="utilization" type="double"/>
<property name="deadline" column="deadline" type="date"/>
<property name="ticketType" column="ticket_type" type="integer"/>
<property name="isCurrentlyAssigned" column="is_currently_assigned" type="boolean"/>
</class>
The UserCalendar.java:
public class UserCalendar implements Serializable {
private static final long serialVersionUID = 10172L;
private long userCalendarId;
private long userId;
private String userLoginName;
private String userName;
private List<UserDate> userDates;
public UserCalendar() {
}
public long getUserCalendarId() {
return userCalendarId;
}
public void setUserCalendarId(long userCalendarId) {
this.userCalendarId = userCalendarId;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserLoginName() {
return userLoginName;
}
public void setUserLoginName(String userLoginName) {
this.userLoginName = userLoginName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<UserDate> getUserDates() {
return userDates;
}
public void setUserDates(List<UserDate> userDates) {
this.userDates = userDates;
}
}
The UserDate.java:
public class UserDate implements Serializable {
private static final long serialVersionUID = 10173L;
private long userDateId;
private Date date;
private List<UserItem> userItems;
public UserDate() {
}
public long getUserDateId() {
return userDateId;
}
public void setUserDateId(long userDateId) {
this.userDateId = userDateId;
}
public void setDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
public List<UserItem> getUserItems() {
return userItems;
}
public void setUserItems(List<UserItem> userItems) {
this.userItems = userItems;
}
}
And the UserItem.java:
public class UserItem implements Serializable {
private static final long serialVersionUID = 10174L;
public static final int AUTO = 1;
public static final int EQUAL = 2;
public static final int CUSTOM = 3;
public static final int CUSTOM_EQUAL = 4;
public static final int GENERAL_TICKET = 5;
public static final int SPECIAL_TICKET_HALF = 6;
public static final int SPECIAL_TICKET_FULL = 7;
private long userItemId;
private long spaceId;
private String spaceName;
private long itemId;
private String itemRefId;
private double allocation;
private int scheduledStrategy;
private double utilization;
private Date deadline;
private int ticketType;
private boolean isCurrentlyAssigned;
public UserItem() {
}
public long getUserItemId() {
return userItemId;
}
public void setUserItemId(long userItemId) {
this.userItemId = userItemId;
}
public long getSpaceId() {
return spaceId;
}
public void setSpaceId(long spaceId) {
this.spaceId = spaceId;
}
public long getItemId() {
return itemId;
}
public void setItemId(long itemId) {
this.itemId = itemId;
}
public double getAllocation() {
return allocation;
}
public void setAllocation(double allocation) {
this.allocation = allocation;
}
public int getScheduledStrategy() {
return scheduledStrategy;
}
public void setScheduledStrategy(int scheduledStrategy) {
this.scheduledStrategy = scheduledStrategy;
}
public double getUtilization() {
return utilization;
}
public void setUtilization(double utilization) {
this.utilization = utilization;
}
public Date getDeadline() {
return deadline;
}
public void setDeadline(Date deadline) {
this.deadline = deadline;
}
public int getTicketType() {
return ticketType;
}
public void setTicketType(int ticketType) {
this.ticketType = ticketType;
}
public String getSpaceName() {
return spaceName;
}
public void setSpaceName(String spaceName) {
this.spaceName = spaceName;
}
public String getItemRefId() {
return itemRefId;
}
public void setItemRefId(String itemRefId) {
this.itemRefId = itemRefId;
}
public boolean isCurrentlyAssigned() {
return isCurrentlyAssigned;
}
public void setCurrentlyAssigned(boolean isCurrentlyAssigned) {
this.isCurrentlyAssigned = isCurrentlyAssigned;
}
}
Now I want to select those UserCalendar object which has a specific itemId. In my thought if I insert userCalendarId in UserItem and execute
SELECT USERCALENDAR
FROM USER_CALENDAR
WHERE USERCALENDAR.USERCALENDARID IN
(SELECT USERCALENDARID
FROM USERITEM
WHERE USERITEM.ITEMID=ID)
then it might be possible.
Am I right?
How can I insert userCalendarId in UserItem? What is the mapping needed for this?
Thanks and regards.
To have one-to-many you will need column in UserDate that refers to UserCalendar.userCalendarId and column in UserItem to refer to UserDate.userDateId. You will need to specify those columns via many-to-one in those classes.
Then you can use join
SELECT * FROM user_calendar uc
JOIN user_date ud ON ud.user_calendar_id=uc.user_calendar_id
JOIN user_item ui ON ui.user_date_id=ud.user_date_id
WHERE ui.user_item_id=<your value>
Assuming that you have those new columns user_calendar_id and user_date_id in user_date and user_item.
In HQL it will be simpler but I don't remember on top of my head. Check docs.
It could be something like
select ui.userDate.userCaledar from UserItem ui where ui.userItemId=:id
Provided that you added properties userDate and userCalendar via many-to-one

Mapping same class relation - continuation

This post is an continuation of this post
I have DlUser Class each object of this class may have DLFaceBook class and each object of DlFaceBook can have Friends which are mapped as myFriends.
I'm trying to map relation of the same class as many to many relation using bag mapping,composite primary key and static inner class. my code is the following:
public class DlUser{
public DlUser(){}
Long Id;
String FirstName;
String LastName;
....
DlFaceBook fbuser;
//// all requred
getters and setters...
}
The Facebook user class looks like this as you can see I have the collection of objectes with the class MyFriends:
public class DlFaceBook {
private long dlpId;
private String FbId;
private Collection<MyFriends> Friends;
public DlFaceBook(){}
public void setFbId(String FbId)
{
this.FbId = FbId;
}
public void setFriends(Collection<MyFriends> friends)
{
this.Friends = friends;
}
public Collection<MyFriends> getFriends()
{
return this.Friends;
}
public void setdlpId(long id)
{
this.dlpId = id;
}
public long getdlpId()
{
return this.dlpId;
}
public String getFbId()
{
return this.FbId;
}
}
MyFriends class looks like this:
public class MyFriends {
private MyFriendsId myFriendId;
private DlFaceBook me;
private DlFaceBook myFriend;
public MyFriendsId getmyFriendId(){
return this.myFriendId;
}
public void setmyFriendId(MyFriendsId fid){
this.myFriendId = fid;
}
public void setme(DlFaceBook me){
this.me = me;
}
public void setmyFriend(DlFaceBook friend){
this.myFriend = friend;
}
public DlFaceBook getme(){
return this.me ;
}
public DlFaceBook getmyFriend(){
return this.myFriend ;
}
public MyFriends(DlFaceBook me, DlFaceBook user){
this.me = me ;
this.myFriend = user;
this.myFriendId = new MyFriendsId(me.getdlpId(),user.getdlpId());
}
public static class MyFriendsId implements Serializable {
private long meId;
private long myFrId;
// getter's and setter's
public MyFriendsId() {}
public MyFriendsId(long meId, long myFriendId) {
this.meId = meId;
this.myFrId = myFriendId;
}
// getter's and setter's
public long getmeId(){
return this.meId;
}
public void setmeId(Integer id){
this.meId = id;
}
public long getmyFrId(){
return this.myFrId;
}
public void setmyFrId(long id){
this.myFrId = id;
}
}
}
Now the Mapping:
DlUser.hbm.xml is the following and it's simple:
<hibernate-mapping>
<class name="DlUser" table="Users">
<id name="Id" column="id" >
<generator class="sequence">
<param name="sequence">userseq</param>
</generator>
</id>
<property name="firstName">
<column name="FirstName" />
</property>
<property name="lastName">
<column name="LastName"/>
</property>
<many-to-one
name="FaceBook"
class="DlFaceBook"
cascade="all"
column="dlpId"
unique="true"
/>
</class>
</hibernate-mapping>
DlFacebook.hbm.xml looks like this:
<hibernate-mapping>
<class name="DlFaceBook" table="dlfacebook">
<id name="dlpId" type="java.lang.Long" column="dlpId">
<generator class="increment" />
</id>
<property name="fbId">
<column name="fbId" />
</property>
<bag name="Friends">
<key column="me_Id" />
<one-to-many class="MyFriends"/>
</bag>
</class>
</hibernate-mapping>
Then MyFriends.hbm.xml looks like this:
<hibernate-mapping>
<class name="MyFriends">
<composite-id name="myFriendId" class="MyFriends$MyFriendsId">
<key-property name="meId"/>
<key-property name="myFrId"/>
</composite-id>
<many-to-one name="me" class="DlFaceBook" insert="false" update="false"/>
<many-to-one name="myFriend" class="DlFaceBook" insert="false" update="false"/>
</class>
</hibernate-mapping>
When I'm executing my query I got the following error:
Hibernate: insert into dlfacebook (fbId, dlpId) values (?, ?)
Hibernate: insert into Users (FirstName, LastName, email, twitter, birthday, dlpId, id) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: update MyFriends set me_Id=? where meId=? and myFrId=?
Hibernate: update MyFriends set me_Id=? where meId=? and myFrId=?
Oct 2, 2010 1:21:18 PM org.hibernate.jdbc.BatchingBatcher doExecuteBatch
SEVERE: Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at Test.main(Test.java:54)
Oct 2, 2010 1:21:18 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at Test.main(Test.java:54)
Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
I see that this error happens when we trying to update not existing row, but how can I make this code work?
Just Facebook and MyFriends
Facebook Notice add convenience method and MutableLong (later, i tell you why to use MutableLong)
public class Facebook {
private MutableLong id = new MutableLong();
public Long getId() { return id.longValue(); }
public void setId(Long id) { this.id.setValue(id); }
public MutableLong getIdAsMutableLong() {
return id;
}
private Collection<MyFriends> myFriends = new ArrayList<MyFriends>();
public Collection<MyFriends> getMyFriends() { return myFriends; }
public void setMyFriends(Collection<MyFriends> myFriends) { this.myFriends = myFriends; }
/**
* add convenience method
*/
public void addFriend(Facebook myFriendFacebook) {
myFriends.add(new MyFriends(this, myFriendFacebook));
}
}
MyFriends
public class MyFriends {
private MyFriendsId myFriendId;
public MyFriendsId getmyFriendId(){ return this.myFriendId; }
public void setmyFriendId(MyFriendsId myFriendId){ this.myFriendId = myFriendId; }
private Facebook me;
public Facebook getme() { return this.me; }
public void setme(Facebook me){ this.me = me; }
private Facebook myFriend;
public Facebook getmyFriend() { return this.myFriend; }
public void setmyFriend(Facebook friend) { this.myFriend = friend; }
public MyFriends() {}
public MyFriends(Facebook meFacebook, Facebook myFriendFacebook){
this.me = meFacebook ;
this.myFriend = myFriendFacebook;
this.myFriendId = new MyFriendsId(meFacebook.getIdAsMutableLong(), myFriendFacebook.getIdAsMutableLong());
}
public static class MyFriendsId implements Serializable {
private MutableLong meId = new MutableLong();
public Long getMeId() { return this.meId.longValue(); }
public void setMeId(Long id) { this.meId.setValue(id); }
private MutableLong myFriendId = new MutableLong();
public Long getMyFriendId(){ return this.myFriendId.longValue(); }
public void setMyFriendId(Long id) { this.myFriendId.setValue(id); }
public MyFriendsId() {}
public MyFriendsId(MutableLong meId, MutableLong myFriendId) {
this.meId = meId;
this.myFriendId = myFriendId;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof MyFriendsId))
return false;
MyFriendsId other = (MyFriendsId) o;
return new EqualsBuilder()
.append(getMeId(), other.getMeId())
.append(getMyFriendId(), getMyFriendId())
.isEquals();
}
#Override
public int hashCode() {
return new HashCodeBuilder()
.append(getMeId())
.append(getMyFriendId())
.hashCode();
}
}
}
Mapping
<hibernate-mapping package="br.com._3845772.model.domain">
<class name="User">
<id name="id">
<generator class="native"/>
</id>
<many-to-one cascade="all" class="Facebook" name="facebook"/>
</class>
<class name="Facebook">
<id name="id">
<generator class="native"/>
</id>
<bag cascade="all" name="myFriends">
<key column="ME_FACEBOOK_ID" update="false"/>
<one-to-many class="MyFriends"/>
</bag>
</class>
<class name="MyFriends">
<composite-id class="MyFriends$MyFriendsId" name="myFriendId">
<key-property column="ME_FACEBOOK_ID" name="meId"/>
<key-property column="MY_FRIEND_FACEBOOK_ID" name="myFriendId"/>
</composite-id>
<many-to-one class="Facebook" column="ME_FACEBOOK_ID" insert="false" name="me" update="false"/>
<many-to-one class="Facebook" column="MY_FRIEND_FACEBOOK_ID" insert="false" name="myFriend" update="false"/>
</class>
</hibernate-mapping>
And this sample
Facebook meFacebook = new Facebook();
Facebook myFriendFacebook = new Facebook();
meFacebook.addFriend(myFriendFacebook);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(myFriendFacebook);
session.save(meFacebook);
session.getTransaction().commit();
session.close();
Which gives me
Hibernate: insert into Facebook values ( )
Hibernate: insert into Facebook values ( )
Hibernate: select myfriends_.ME_FACEBOOK_ID, myfriends_.MY_FRIEND_FACEBOOK_ID from MyFriends myfriends_ where myfriends_.ME_FACEBOOK_ID=? and myfriends_.MY_FRIEND_FACEBOOK_ID=?
Hibernate: insert into MyFriends (ME_FACEBOOK_ID, MY_FRIEND_FACEBOOK_ID) values (?, ?)
A couple of notes
Hibernate does not support automatic generation of composite primary key. You must set up its value before saving
Your database must support the target generator strategy (If you does not know which generator strategy your database support, prefer to use a native strategy)
Each entity must supply a no-arg constructor
Now why MutableLong (encapsulated by a Long property) instead of Long ?
Number and its subclasses (Long is a Number) are immutable. So if you want Facebook.id (configured by database) and its counterpart MyFriend$MyFriendId.meId share the same value, you must use MutableLong. When the database set up Facebook.id, MyFriend$MyFriendId.meId automatically get its newest value. But it just occurs if you use a MutableLong.

Categories