Pab*_*ais 5 java hibernate jpa
我正在尝试在 JPA 中映射下图中描述的一对多表关系:

如可以看到的,"activity_property"表使用与复合主键(id,name)和列"id"是一个外键列"id"在表中"activity"。
我当前的实体是这样映射的(为了清楚起见,省略了一些辅助方法):
@Entity
@Getter
@Setter
public class Activity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "act_id_generator")
@SequenceGenerator(name = "act_id_generator", sequenceName = "activity_id_seq", allocationSize = 1, initialValue = 1)
private Integer id;
private String name;
@OneToMany(mappedBy = "id.activityId", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ActivityProperty> properties;
}
Run Code Online (Sandbox Code Playgroud)
@Entity
@Getter
@Setter
@Table(name = "activity_property")
public class ActivityProperty {
@EmbeddedId
private ActivityPropertyId id;
private String value;
@Enumerated(EnumType.STRING)
private PropertyType type;
}
Run Code Online (Sandbox Code Playgroud)
@Embeddable
@Getter
@Setter
@ToString
public class ActivityPropertyId implements Serializable {
@Column(name = "id")
private Integer activityId;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ActivityPropertyId that = (ActivityPropertyId) o;
return activityId.equals(that.activityId) &&
name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(activityId, name);
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试以这种方式坚持一项活动时:
Activity activity = createActivity("Activity_1");
activity.addProperty(ActivityProperty.from("Prop1", "value1", PropertyType.PARAMETER));
activityDAO.persist(activity);
Run Code Online (Sandbox Code Playgroud)
我可以在 Hibernate 中看到以下痕迹:
Hibernate: call next value for activity_id_seq
Hibernate: insert into activity (name, id) values (?, ?)
Hibernate: insert into activity_property (type, value, id, name) values (?, ?, ?, ?)
05-05-2019 12:26:29.623 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper.logExceptions - SQL Error: 23502, SQLState: 23502
05-05-2019 12:26:29.624 [main] ERROR o.h.e.jdbc.spi.SqlExceptionHelper.logExceptions - NULL not allowed for column "ID"; SQL statement:
insert into activity_property (type, value, id, name) values (?, ?, ?, ?) [23502-199]
Run Code Online (Sandbox Code Playgroud)
似乎自动生成的 idActivity没有用于ActivityProperty.
我不知道如何正确映射这种关系。我的 JPA 注释中是否缺少任何内容?
据我所知,JPA 不支持通过cascade操作来实现这一点。你对JPA的要求太高了。我没有具体的参考资料来说明这一点,但您可以使用下面的代码尽可能接近。它不会运行,因为 hibernate(至少)不知道如何自动将 映射activity.id到类的 PK ActivityProperty。
@Entity
@Getter
@Setter
@Table(name = "activity_property")
@IdClass(ActivityPropertyId.class)
public class ActivityProperty {
@ManyToOne
@Id
@JoinColumn(name="id", referencedColumnName="id")
private Activity activity;
@Id
private String name;
private String value;
}
@Getter
@Setter
@ToString
public class ActivityPropertyId implements Serializable {
public ActivityPropertyId() {}
@Column(name = "id")
private Integer activity;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ActivityPropertyId that = (ActivityPropertyId) o;
return activity.equals(that.activity) &&
name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(activity, name);
}
}
Run Code Online (Sandbox Code Playgroud)
这将给出例外
引起原因:java.lang.IllegalArgumentException:无法将 java.lang.Integer 字段 model.ActivityPropertyId.activity 设置为 model.Activity
我还没有看到任何解决这个问题的好方法。恕我直言,cascade这是一个傻瓜的天堂,您应该ActivityProperty自己保存实例并仅使用双向映射进行查询。这确实是它的用途。如果您OneToMany通过级联对列表执行一些简单的保存操作并查看生成的 SQL,您会看到可怕的事情。
| 归档时间: |
|
| 查看次数: |
4022 次 |
| 最近记录: |