如何使OpenJPA 2.2.0不持久的外键 [英] how to make openjpa 2.2.0 not persist foreign key

查看:89
本文介绍了如何使OpenJPA 2.2.0不持久的外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个桌子. 资产表

ASSET_ID SYSIBM INTEGER 4 0否
USER_ID SYSIBM INTEGER 4 0否
ASSET_TYPE_ID SYSIBM SMALLINT 2 0否
ACCESSIBILITY_ID SYSIBM SMALLINT 2 0是
DOWNLOAD_TYPE_ID SYSIBM SMALLINT 2 0否
ASSET_STATUS_ID SYSIBM SMALLINT 2 0否
ASSET_MARKETING_ID SYSIBM SMALLINT 2 0是
ASSET_PI_SPI_ID SYSIBM SMALLINT 2 0是

和访问权限表

ACCESSIBILITY_ID SYSIBM SMALLINT 2 0否
ACCESSIBILITY_DESC SYSIBM VARCHAR 50 0否

我有两个豆子,

Asset Bean

和可访问性

@Column(name="ACCESSIBILITY_ID")
private short accessibilityId;

@Column(name="ACCESSIBILITY_DESC")
private String accessibilityDesc;

@OneToMany(mappedBy="accessibilityId",cascade=CascadeType.REMOVE,fetch=FetchType.LAZY)  
private Set<Asset> assetCollection;

在我的ManagerBean中调用EntitiManager.flush()时

 em.persist(asset);  
 em.flush();

我得到

javax.ejb.EJBException:请参见嵌套异常;请参见嵌套异常.嵌套的异常是:org.apache.openjpa.persistence.InvalidStateException:在生命周期状态下遇到非托管对象"com.ibm.tap.ejb.dao.entity.Accessibility@169e3455"处于非托管状态,同时通过字段"com.ibm.tap"级联持久性"ejb.dao.entity.Asset.accessibilityId".但是,此字段不允许层叠保留.您不能刷新非托管对象或与非托管对象具有持久关联的图形.建议采取的措施:a)将此字段的级联属性设置为CascadeType.PERSIST或CascadeType.ALL(JPA批注)或"persist"或"all"(JPA orm.xml),b)在全局启用级联持久性,c)手动启用在刷新之前保留相关字段值. d)如果引用属于另一个上下文,则可以通过设置StoreContext.setAllowReferenceToSiblingContext()来允许对其进行引用. FailedObject:com.ibm.tap.ejb.dao.entity.Accessibility@169e3455

我尝试将Asset类更改为

@ManyToOne(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY)
@JoinColumn(name="ACCESSIBILITY_ID")
@ForeignKey
private Accessibility accessibilityId;

当我这样做时,我得到 javax.ejb.EJBException:请参见嵌套异常;嵌套的异常是:org.apache.openjpa.persistence.EntityExistsException:在此上下文中已经存在类型为"com.ibm.tap.ejb.dao.entity.Accessibility"的对象,其对象为oid.另一个不能持久. FailedObject:com.ibm.tap.ejb.dao.entity.Accessibility@166c27b9

对我来说有意义的是,我正在尝试保留已经拥有的表.我究竟做错了什么?

解决方案

您遇到的问题不是由外键引起的.发生的情况是您的Asset对象包含一个不受OpenJPA管理的Accessibility对象.如何解决此问题取决于辅助功能记录的状态:

  1. 数据库中是否已经存在辅助功能记录?如果是这样,请先使用getEntityManager.find(Accessibility.class,uid)加载它,然后再将其设置到您的Asset对象上,然后再尝试保留该Asset对象.

  2. 如果可访问性记录尚未持久化,则需要先使用"getEntityManager.persist(accessibility)"来对其进行持久化,然后再将其设置到您的Asset对象上,然后再尝试对其进行持久化.或者,您的另一种选择是更改可访问性集合的级联类型以允许持久化,如下所示:

@ManyToOne(cascade=cascade={ CascadeType.PERSIST, CascadeType.REMOVE },fetch=FetchType.LAZY)
@JoinColumn(name="ACCESSIBILITY_ID")
@ForeignKey
private Accessibility accessibilityId;

如果更改了cacade,则在持久化Asset对象时,资产对象上所有未持久的Accessibility对象都会自动持久化.

I have two tables.. Asset table

ASSET_ID SYSIBM INTEGER 4 0 No
USER_ID SYSIBM INTEGER 4 0 No
ASSET_TYPE_ID SYSIBM SMALLINT 2 0 No
ACCESSIBILITY_ID SYSIBM SMALLINT 2 0 Yes
DOWNLOAD_TYPE_ID SYSIBM SMALLINT 2 0 No
ASSET_STATUS_ID SYSIBM SMALLINT 2 0 No
ASSET_MARKETING_ID SYSIBM SMALLINT 2 0 Yes
ASSET_PI_SPI_ID SYSIBM SMALLINT 2 0 Yes

and the Accesibility table

ACCESSIBILITY_ID SYSIBM SMALLINT 2 0 No
ACCESSIBILITY_DESC SYSIBM VARCHAR 50 0 No

i have two beans,

Asset Bean

@Column(name="ASSET_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int assetId;

@Column(name="DATE_CREATED")
private Timestamp dateCreated;

@Column(name="LAST_UPDATED")
private Timestamp lastUpdated;

@Column(name="DATE_PUBLISHED")
private Timestamp datePublished;

@Column(name="ASSET_SURVEY")
private Short assetSurvey;

@Column(name="ASSET_HELP")
private Short assetHelp;

@Column(name="ACCEPTED_TERMS")
private Short acceptedTerms;

@Column(name="ASSET_DESC")
@Lob
private String assetDesc;

@Column(name="ASSET_ALIAS")
private String assetAlias;

@Column(name="ASSET_TITLE")
private String assetTitle;

@Column(name="ASSET_SUMMARY")
private String assetSummary;

@Column(name="ASSET_URL")
private String assetUrl;

@Column(name="ASSET_ORIGINALITY")
private Short assetOriginality; 

@Column(name="ASSET_INVENTION")
private Short invationDisclosure;

@Column(name="ASSET_PRIVACY")
private String  privacyCompliance;  


@ManyToOne
@JoinColumn(name="ASSET_PI_SPI_ID")
private AssetPiSpi assetPiSpiId;

@ManyToOne
@JoinColumn(name="ASSET_MARKETING_ID")
@ForeignKey
private AssetMarketing assetMarketingId;    

@ManyToOne(cascade=CascadeType.REMOVE,fetch=FetchType.LAZY)
@JoinColumn(name="ACCESSIBILITY_ID")
@ForeignKey
private Accessibility accessibilityId;

and Accessibility

@Column(name="ACCESSIBILITY_ID")
private short accessibilityId;

@Column(name="ACCESSIBILITY_DESC")
private String accessibilityDesc;

@OneToMany(mappedBy="accessibilityId",cascade=CascadeType.REMOVE,fetch=FetchType.LAZY)  
private Set<Asset> assetCollection;

when the EntitiManager.flush() get's called in my ManagerBean

 em.persist(asset);  
 em.flush();

I am getting

javax.ejb.EJBException: See nested exception; nested exception is: org.apache.openjpa.persistence.InvalidStateException: Encountered unmanaged object "com.ibm.tap.ejb.dao.entity.Accessibility@169e3455" in life cycle state unmanaged while cascading persistence via field "com.ibm.tap.ejb.dao.entity.Asset.accessibilityId" during flush. However, this field does not allow cascade persist. You cannot flush unmanaged objects or graphs that have persistent associations to unmanaged objects. Suggested actions: a) Set the cascade attribute for this field to CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or "persist" or "all" (JPA orm.xml), b) enable cascade-persist globally, c) manually persist the related field value prior to flushing. d) if the reference belongs to another context, allow reference to it by setting StoreContext.setAllowReferenceToSiblingContext(). FailedObject: com.ibm.tap.ejb.dao.entity.Accessibility@169e3455

i have tried changing the Asset class to

@ManyToOne(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY)
@JoinColumn(name="ACCESSIBILITY_ID")
@ForeignKey
private Accessibility accessibilityId;

When i do that i get javax.ejb.EJBException: See nested exception; nested exception is: org.apache.openjpa.persistence.EntityExistsException: An object of type "com.ibm.tap.ejb.dao.entity.Accessibility" with oid "1" already exists in this context; another cannot be persisted. FailedObject: com.ibm.tap.ejb.dao.entity.Accessibility@166c27b9

Which make sense to me that i am trying to persist the table i already have. What am i doing wrong?

解决方案

The issue you are having isn't caused by foreign keys. What is happening is that your Asset object contains an Accessibility object that is not being managed by OpenJPA. How to fix this depends on the state of the Accessibility record:

  1. Does the Accessibility record already exist in the database? If so, load it using getEntityManager.find(Accessibility.class, uid) first, and then set it onto your Asset object before you try to persist the Asset object.

  2. If the Accessibility record hasn't already been persisted, then need to persist it first using "getEntityManager.persist(accessibility)" and then set it onto your Asset object before you try to persist it. Or, your other option is to change the cascade type for your accessibility collection to allow persisting, as follows:

@ManyToOne(cascade=cascade={ CascadeType.PERSIST, CascadeType.REMOVE },fetch=FetchType.LAZY)
@JoinColumn(name="ACCESSIBILITY_ID")
@ForeignKey
private Accessibility accessibilityId;

If you make the cacade change, then any unpersisted Accessibility object on your Asset object will be persisted automatically when you persist the Asset object.

这篇关于如何使OpenJPA 2.2.0不持久的外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆