开发者

Composite Primary Key Not getting updated correctly with with EclipseLink. Where as with hibernate, it does. Why?

I posted all the code and an issue with selection here.

Now I am going to ask one more problem I have seen with eclipselink which I havent seen with hibernate.

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 :

//Parent class
@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;

   ...
}

Now lets see its child and its @EmbeddedId PK class:

@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;

}

My 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 = new 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. With hibernate, it worked perfectly fine.

Lets change persistence provider to eclipselink. Let us now use eclipselink and see the same issue. Now with eclipse link, after fixing the issue mentioned in Problem 1,

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 ?

I can understand why its inserting 1 in the second insert statement in profile_basket_table as 1 is the default value. But, why it is updating 1 in profile_id column of profile_basket_table.

With hibernate, the third update stetement perfectly updated profile_id to 1130. But why eclipselink is not updating the profile_id from Profile to ProfileItem???

Whyy ??

Can anyone please answer ? Where is so called portability ?? Are those known bugs with eclipselink ?

Thanks.

Arun Kandregula.


The first issue was because of a bug fixed in the latest EclipseLink (2.3). This issue though is because of how you have it defined - the ProfileItem.profile_id field is mapped twice. Once because of how it is mapped in ProfileItem through its embeddedid's keyId mapping, the second is because it can also be set through the Profile->ProfileItem relationship. As was suggested in the other forum post for the first issue, the best way to map this would be instead to have a OneToMany with a ManyToOne back pointer to set the ProfileItem's profile_id. This would make JPA set the value instead of the application needing to get the value from Profile and manually set it in the keyId.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜