Hello friends,
I have 1 Profile and * ProfileItem.
1 Profile --- * ProfileItems ( One profile can have Many ProfileItems).
Note : 1. Its a one-to-many relationship from profile to profileItem.
2. Its a unidirectional relationship.
PK for Profile is profile_id.
PK for ProfileItem is a composite primary key ( profile_id, from_id )
Firstly, I would I like to complain that EclipseLink doesnt work
like Hibernate :
1st Problem with
EclipseLink:
Just becasue I have a composite primary key in child entity called
ProfileItem, its forcing me to use JoinColumns. I cant use
@JoinColumns as other column from_id is not a foreign key to any
other table.
I initially used same annotation which worked perfectly with hibernate
as follows :
@Entity
@Table(name="profile_table")
class Profile {
@Id
@Column(name="profile_id")
private Integer profileId ;
...
/**
* WORKS WITH HIBERNATE AS PERSISTENCE PROVIDER, BUT FAILS WITH
ECLIPSELINK
*/
@OneToMany( cascade = CascadeType.ALL )
@JoinColumn( name= "profile_id", referencedColumnName="profile_id"
)
private Set<XVMUpdateProfileItem> profileItems =
null;
...
}
Above code throws following error with eclipselink :
The @JoinColumns on the
annotated element [field profileItems] from the entity class [class
arun.ucerelay.datastructures.XVMUpdateProfile] is incomplete. When
the source entity class uses a composite primary key, a @JoinColumn
must be specified for each join column using the @JoinColumns. Both the
name and the referencedColumnName elements must be specified in each
such @JoinColumn.
Some how I managed to get this working for loading profiles and related
profile items.
THIS DOESNT MAKE ANY SENSE TO DECLARE SAME @JoinColumn AGAIN...BUTS
FUNNILY WORKS WITH ECLIPSELINK. This is a bug.
/**
* WORKS WITH ECLIPSELINK AS PERSISTENCE PROVIDER
*/
@OneToMany( cascade = CascadeType.ALL)
@JoinColumns({
@JoinColumn( name= "profile_id", referencedColumnName="profile_id"
, insertable = true, updatable = true),
@JoinColumn( name= "profile_id", referencedColumnName="profile_id"
, nullable = false)
})
private Set<XVMUpdateProfileItem> profileItems =
null;
If any one can tell me any right way of implementing unidirectional
relationship, please tell me.
2nd Problem with
EclipseLink:
Now that I managed to get loading working, I tried my hands at saving
profile and cascading the save operation for related child ProfileItem
entities.
With Hibernate, this is how I coded which worked perfectly fine :
@Entity
@Table(name="profile_table")
public class
XVMUpdateProfile implements Serializable {
@Id
@Column(name="profile_id")
@TableGenerator(name =
"UCERELAY_TABLE_GENERATOR",
table=
"SEQUENCE",
pkColumnName="SEQ_NAME",
valueColumnName ="SEQ_COUNT",
pkColumnValue="PROFILE_SEQ",
initialValue = 30,
allocationSize = 10)
@GeneratedValue(strategy = GenerationType.TABLE, generator =
"UCERELAY_TABLE_GENERATOR")
private Integer
profileId ;
...
/**
* WORKS WITH
HIBERNATE AS PERSISTENCE PROVIDER
*/
@OneToMany( cascade =
CascadeType.ALL )
@JoinColumn( name=
"profile_id", referencedColumnName="profile_id" )
private
Set<XVMUpdateProfileItem> profileItems = null;
...
}
@Entity
@Table(name="profile_basket_
table")
public class XVMUpdateProfileItem implements Serializable,
Comparable<XVMUpdateProfileItem> {
private static Log logger = LogFactory.getLog(XVMUpdateProfileItem.class);
private static final long serialVersionUID = 1L;
@EmbeddedId
private XVMUpdateProfileItemPK key;
...
}
@Embeddable
public class
XVMUpdateProfileItemPK implements Serializable, Comparable<XVMUpdateProfileItemPK>
{
private static final
long serialVersionUID = 1L;
@Column(name="profile_id", nullable=false)
private int keyId =
1; // assigned a default value.
@Column(name="from_node", nullable=false)
private int fromNode =
-2;
}
-- Main Program ---
public class UpdateProfileSave3 {
private static Log logger = LogFactory.getLog(UpdateProfileMain.class);
private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("usinghibernate");
public static void main(String args[]) {
List<XVMUpdateProfile> profiles = new
ArrayList<XVMUpdateProfile>();
try {
// First unit of work
EntityManager em = emf.createEntityManager();
EntityTransaction etx = em.getTransaction();
etx.begin();
XVMUpdateProfile profile = "" XVMUpdateProfile();
profile.setCreatorId(90);
profile.setProfileDescription("Newly created to check
generation of id");
profile.setProfileName("Mahesh Babu Profile");
Set<XVMUpdateProfileItem> items =
profile.getProfileItems();
XVMUpdateProfileItem newItem = new XVMUpdateProfileItem();
newItem.setAction(XVMUpdateAction.ITEM_INSTALL);
newItem.getKey().setFromNode(90);
items.add(newItem);
profile.setProfileItems(items);
em.persist(profile);
etx.commit();
em.close();
}catch(Exception ex){
logger.debug(" Arun Could not load profiles : " +
ex.getMessage());
ex.printStackTrace();
}
}
}
----------------------------
I created one parent entity ( profile ) and attached one child entity (
profile_item ) and saved the parent entity ( profile ). I expected it
to insert one profile and one profile_item with correct profile_id.
As expected it did that with 3 DML statements :
insert into profile_table (creator_manager_id, lastupdate,
description, profile_name, creatorname, profile_id) values (90,
'2011-04-01 15:23:48', 'Newly created to check generation of id',
'Mahesh Babu Profile', 'Unspecified', 1130);
insert into profile_basket_table (action, from_node, profile_id)
values (9, 90, 1)
update profile_basket_table set profile_id=1130
where from_node=90 and profile_id=1
DB results :
select PROFILE_ID, CREATOR_MANAGER_ID from profile_table
where profile_id = 1130;
PROFILE_ID
CREATOR_MANAGER_ID
---------------------- ----------------------
1130 90
select * from profile_basket_table where profile_id = 1130;
FROM_NODE PROFILE_ID
ACTION
---------------------- ---------------------- ----------------------
90 1130 4
It inserted parent and child as expected.
Now it eclipse link, after fixing the issue mentioned in Problem 1
above,
I tried to execute the same problem, with fix to a single line :
private static
EntityManagerFactory emf = Persistence.createEntityManagerFactory("usingeclipselink");
It also issues 3 statements. But last update statement was erroneous.
INSERT INTO profile_table (profile_id, lastupdate, creator_manager_id,
description, creatorname, profile_name) VALUES (?, ?, ?, ?, ?, ?)
bind => [115, 2011-04-01 15:37:13.257, 90, Newly created to
check generation of id, Unspecified, Mahesh Babu Profile]
INSERT INTO profile_basket_table (action, from_node, profile_id) VALUES
(?, ?, ?)
bind => [4, 90, 1]
UPDATE profile_basket_table SET profile_id
= ? WHERE ((profile_id = ?) AND (from_node = ?))
bind => [1, 1, 90]
Can someone address the problems I mentioned in above mail ?
Are those known bugs with eclipselink ?
--
Thanks,
Arun Kandregula.
|