简体   繁体   English

当目标是组合键时,Hibernate不保存ManyToOne

[英]Hibernate not saving ManyToOne when target is composite key

Hibernate does not seem to be updating an FK reference when the object of that association is a composite key. 当该关联的对象是组合键时,Hibernate似乎没有更新FK引用。

The transaction succeeds (no error, no stack trace), but there is no update statement generated (I have hibernate logging enabled). 事务成功(没有错误,没有堆栈跟踪),但是没有生成更新语句(我启用了休眠日志记录)。

I have tried all manner of cascade annotations (no cascade, ALL, PERSIST, even SAVE_UPDATE) without any change to the symptoms. 我尝试了所有方式的级联批注(无级联,ALL,PERSIST甚至SAVE_UPDATE),而症状没有任何变化。 This no-update symptom exists both from an on-line OpenXava screen as well as from custom Java code (in an OpenXava action). 在线OpenXava屏幕以及自定义Java代码(在OpenXava操作中)都存在这种不更新的症状。

The application database has requirements to allow external uploads to tables, so I have been told that switching to system-assigned keys is not an option they are willing to pursue. 应用程序数据库要求允许外部上载到表,因此有人告诉我,他们不愿意选择切换到系统分配的键。

The owning association (currently without any cascade setting): 所属关联(当前没有任何级联设置):

  @ManyToOne(fetch=FetchType.LAZY,optional=false)
  @Required
  @JoinColumns({
    @JoinColumn(name="programID",referencedColumnName="programID",nullable=false,unique=false,insertable=false,updatable=false),
    @JoinColumn(name="projectID",referencedColumnName="projectID",nullable=false,unique=false,insertable=false,updatable=false)
  })
  @DescriptionsList(descriptionProperties="parentProgram.programName,projectName")
  @ReferenceView("reference")
  private Project associatedProject;

The inverse association: 逆关联:

  @OneToMany(mappedBy="associatedProject",fetch=FetchType.LAZY) //No cascade allowed
  @ReadOnly
  private Set<Asset> assets = new HashSet<Asset>();

Does anyone know if there is an open Hibernate bug on this? 有人知道这是否有一个开放的Hibernate错误吗? I have not been able to find any using Google search, but perhaps someone has first-hand experience. 我无法使用Google搜索找到任何内容,但也许有人有第一手经验。

Thanks, Roy. 谢谢,罗伊。

EDIT: As a work-around, I tried to write my own HQL update. 编辑:作为一种变通办法,我试图编写自己的HQL更新。

update Asset set associatedProject = :ap where assetKey = :key

That fails on an obtuse Hibernate syntax error unexpected AST node: AND while processing the SET clause. 在处理SET子句时unexpected AST node: AND在钝的Hibernate语法错误unexpected AST node: AND上失败了。

update Asset set associatedProject.projectId = :projId, associatedProject.parentProgram = :pgm where assetKey = :key

That generated update Asset cross join set projectID=?, programID=? where assetKey=? 生成的update Asset cross join set projectID=?, programID=? where assetKey=? update Asset cross join set projectID=?, programID=? where assetKey=? and then failed on invalid syntax at "cross" 然后在“ cross”处使用无效语法失败

However, doing my own SQL update works. 但是,执行我自己的SQL更新是可行的。

Does anyone have a better work-around? 有谁有更好的解决方法? Or any further thoughts on the root problem? 或对根本问题有任何进一步的想法?

In my opinion, this still points to a Hibernate bug (of course it's a bug -- you can't just skip an update without any errors or messages) with composite key handling. 在我看来,这仍然指向具有复合键处理的Hibernate错误(当然,这是一个错误-您不能只跳过没有任何错误或消息的更新)。

Hibernate does not save the relationship because you say it that doesn't save it. Hibernate不会保存该关系,因为您说它不会保存该关系。 Just remove the insertable=false,updatable=false from your two @JoinColumn. 只需从两个@JoinColumn中删除insertable = false,updatable = false即可。

Here is a start on how you might use "derived identity" to map your primary keys, and this might help. 这是您如何使用“派生身份”来映射主键的开始,这可能会有所帮助。 I'm just guessing at your model. 我只是在猜测您的模型。 But it's a start.... 但这是一个开始。

@Entity
public class Program {
    @Id
    int id;

    @OneToMany(mappedBy="program")
    Set<Project> projects;

    ...
}

@Embeddable
public class ProjectID {
    int projectID;
    int programID; // corresponds to the type of Program's primary key

    ...
}

@Entity
public class Project {
    @EmbeddedId
    ProjectID id;

    @MapsId("programID") // maps 'programID' attribute of embedded ID
    @ManyToOne
    Program program;

    @OneToMany(mappedBy="associatedProject", fetch=FetchType.LAZY)
    Set<Asset> assets;

    ...
}

@Embeddable
public class AssetID {
    int assetID;
    ProjectID projectID; // corresponds to the type of Project's primary key

    ...
}

@Entity
public class Asset {
    @EmbeddedId
    AssetID id;

    @MapsId("projectID") // maps 'projectID' attribute of embedded ID
    @ManyToOne(fetch=FetchType.LAZY, optional=false)
    Project associatedProject;

    ...
}

Derived identities are discussed in the JPA 2.1 spec, section 2.4.1. JPA 2.1规范的第2.4.1节中讨论了派生身份。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM