JPA:使用复合键的多个一对多关系

时间:2017-07-26 15:05:06

标签: java mysql sql hibernate jpa

我有这些实体:

@Entity @Table(name = "run") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "runId") public class Run implements Serializable { /** * */ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "run_id") private Long runId; @Column(name = "status") private Integer status; @Column(name = "create_date") private Date date; @Column(name = "config_id") private Long configId; @Column(name = "stream_id") private Long streamId; @OneToOne(mappedBy = "run", cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "run_id", unique = true, nullable = true, insertable = true, updatable = true) private StreamRun streamRun; ... } 实体:

StreamRun

@Entity @Table(name = "stream_run") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "streamId") public class StreamRun implements Serializable { /** * */ private static final long serialVersionUID = 1L; @Id @Column(name = "id") private Long streamId; @Column(name = "run_id", insertable = false, updatable = false) private Long runId; @Column(name = "stream_name") private String streamName; @OneToOne @JoinColumn(name = "run_id") private Run run; @OneToMany(cascade = CascadeType.ALL, mappedBy = "stream", orphanRemoval = true, targetEntity = JobRun.class) private List<JobRun> jobs = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, mappedBy = "streamRun", orphanRemoval = true, targetEntity = StreamEvent.class) private List<StreamEvent> events = new ArrayList<>(); .... } 实体:

JobRun

@Entity @Table(name = "jobs_run") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @IdClass(JobRunKey.class) public class JobRun implements Serializable { /** * */ private static final long serialVersionUID = 1L; @Id @Column(name = "id") private Long id; @Id @Column(name = "run_id", insertable = false, updatable = false) private Long runId; @Column(name = "name") private String name; @Column(name = "type") private String jobType; @Column(name = "script") private String script; @Column(name = "status") private Integer status; @ManyToOne @JoinColumns({ @JoinColumn(name = "run_id", referencedColumnName = "run_id"), @JoinColumn(name = "job_stream_id", referencedColumnName = "id") }) private StreamRun stream; @OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobDependencyRun.class) public List<JobDependencyRun> dependencies = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobEvent.class) public List<JobEvent> events = new ArrayList<>(); .... } 实体:

job_run

所有列都在MySQL数据库中定义,表id的复合键为(run_idJobRun)。

问题出在@ID实体:

  • 如果我将“run_id”字段定义为@ID,则会出现异常(插入时)

      

    参数索引超出范围(8>参数个数,即7)。

  • 如果我在没有run_id的情况下定义它,则会出现异常(更新时)

      

    为'PRIMARY'键重复输入'4-78'

  • 如果我从实体中删除整个字段定义,因为它是外键,那么异常将是:

      

    无法找到逻辑名为melt

    的列

    “虽然该列存在于表格中。”

拜托,有人可以帮帮我吗? 我在代码中做错了吗?

1 个答案:

答案 0 :(得分:1)

我设法找到了一个解决方案,通过修改JobRun实体,如下所示,并从直接的setter和getter方法更改\访问runId的值。

@Entity
@Table(name = "jobs_run")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, 
property = "id")
@IdClass(JobRunKey.class)
public class JobRun implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id")
    private Long id;

    @Id
    @Column(name = "run_id")
    private Long runId;

    @Column(name = "job_stream_id")
    private Long streamId;

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

    @Column(name = "type")
    private String jobType;

    @Column(name = "script")
    private String script;

    @Column(name = "status")
    private Integer status;

    @ManyToOne
    @JoinColumns({ @JoinColumn(name = "run_id", referencedColumnName = "run_id", insertable = false, updatable = false),
            @JoinColumn(name = "job_stream_id", referencedColumnName = "id", insertable = false, updatable = false) })
    private StreamRun stream;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobDependencyRun.class)
    public List<JobDependencyRun> dependencies = new ArrayList<>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobEvent.class)
    public List<JobEvent> events = new ArrayList<>();
    ...
}