简体   繁体   中英

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.

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. This no-update symptom exists both from an on-line OpenXava screen as well as from custom Java code (in an OpenXava action).

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? I have not been able to find any using Google search, but perhaps someone has first-hand experience.

Thanks, Roy.

EDIT: As a work-around, I tried to write my own HQL update.

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.

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=? and then failed on invalid syntax at "cross"

However, doing my own SQL update works.

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 does not save the relationship because you say it that doesn't save it. Just remove the insertable=false,updatable=false from your two @JoinColumn.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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