复合主键未通过 EclipseLink 正确更新。与休眠一样,确实如此。为什么?

发布于 2024-10-29 03:58:25 字数 5650 浏览 4 评论 0原文

我发布了所有代码和选择问题

现在我要问一个我在 eclipselink 中遇到过但在 hibernate 中没有遇到过的问题。

现在我设法开始加载工作,我尝试保存配置文件并级联相关子 ProfileItem 实体的保存操作。

使用 Hibernate,这就是我的编码方式,效果非常好:

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

   ...
}

现在让我们看看它的子实体及其 @EmbeddedId PK 类:

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

}

我的主程序:

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();
        }           
}

我创建了一个父实体( profile )并附加了一个子实体( profile_item )并保存了父实体( 轮廓 )。我希望它能够插入一个配置文件和一个具有正确 profile_id 的 profile_item。

正如预期的那样,它使用 3 个 DML 语句做到了这一点:

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                     

它按预期插入了父级和子级。使用休眠功能,它工作得非常好。

让我们将持久性提供程序更改为 eclipselink。 现在让我们使用 eclipselink 来看看同样的问题。 现在有了 Eclipse 链接,修复了 问题 1

我尝试执行相同的问题,但修复了一行:

   private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("usingeclipselink");

它还发出了 3 个语句。但上次更新声明是错误的。

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] 

有人可以解决我在上面邮件中提到的问题吗?

我可以理解为什么它在 profile_basket_table 的第二个插入语句中插入 1,因为 1 是默认值。 但是,为什么它在 profile_basket_table 的 profile_id 列中更新 1。

使用hibernate,第三次更新stetement完美地将profile_id更新为1130。 但为什么 eclipselink 不将 profile_id 从 Profile 更新为 ProfileItem???

为什么??

有人可以回答吗?所谓的可移植性在哪里? eclipselink 存在这些已知错误吗?

谢谢。

阿伦·坎德雷古拉。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怼怹恏 2024-11-05 03:58:25

第一个问题是由于最新的 EclipseLink (2.3) 中修复的错误。但此问题是由于您的定义方式所致 - ProfileItem.profile_id 字段映射了两次。一是因为它是如何通过其embeddedid的keyId映射映射到ProfileItem中的,二是因为它也可以通过Profile->ProfileItem关系来设置。正如第一期的其他论坛帖子中所建议的,映射此问题的最佳方法是使用 OneToMany 和 ManyToOne 后向指针来设置 ProfileItem 的 profile_id。这将使 JPA 设置值,而不是应用程序需要从 Profile 获取值并在 keyId 中手动设置它。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文