新 Table 已创建,而不是更新现有的。一对多映射与复合键,弹簧启动,休眠
New Table Created intead of updating existing one. OneToMany mapping with CompositeKey, springboot , hibernate
我的架构中有两个 table,它们之间存在一对多关系。
单位和unit_bridge
单元有 2 列 id 和 name
unit_bridge 有两列,unit_master_id 和 unit_slave_id。两者一起组成一个复合键。这里unit_slave_id是id[=55=的外键] 单位列。
当我收到 POST 请求时,正在创建一个名为 unit_child_units[=55 的新 table =] 在数据库中。并且 unit_bridge 正在更新为 unit_slave_id 列的错误值。
尽管 unit_master_id 的值在 unit_bridge table 中是正确的,但它对应的是 unit_slave_id 映射错了。
我不想要新的 table,而是想更新我的 unit_bridge table,因为我收到 POST用户请求 单位 table.
这是我的 json 请求,
{
"name" : "john doe",
"childUnits" : [
{
"unitBridgeId" :{
"unit_master_id" : 4
}
}
]
}
这是我的模型。
Unit.java
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Entity
@Table(name="unit")
@JsonInclude(Include.NON_NULL)
public class Unit implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@Transient
private int parent_id;
@OneToMany(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
private Set<UnitBridge> childUnits = new HashSet<UnitBridge>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getParent_id() {
return parent_id;
}
public void setParent_id(int parent_id) {
this.parent_id = parent_id;
}
public Set<UnitBridge> getChildUnits() {
return childUnits;
}
public void setChildUnits(Set<UnitBridge> childUnits) {
this.childUnits = childUnits;
}
@Override
public String toString() {
return "Unit [id=" + id + ", name=" + name + ", parent_id=" + parent_id + ", childUnits=" + childUnits + "]";
}
}
UnitBridge.java
import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Entity
@Table(name="unit_bridge")
@JsonInclude(Include.NON_NULL)
public class UnitBridge implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@EmbeddedId
private UnitBridgeId unitBridgeId;
@Override
public String toString() {
return "UnitBridge [unitBridgeId=" + unitBridgeId + "]";
}
public UnitBridgeId getUnitBridgeId() {
return unitBridgeId;
}
public void setUnitBridgeId(UnitBridgeId unitBridgeId) {
this.unitBridgeId = unitBridgeId;
}
public int getUnit_master_id() {
return unitBridgeId.getUnit_master_id();
}
public int getUnit_slave_id() {
return unitBridgeId.getUnit_slave_id();
}
public void setUnit_master_id(int unit_master_id) {
unitBridgeId.setUnit_master_id(unit_master_id);
}
public void setUnit_slave_id(int unit_slave_id) {
unitBridgeId.setUnit_slave_id(unit_slave_id);
}
}
UnitBridgeId.java
import java.io.Serializable;
import javax.persistence.Embeddable;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Embeddable
public class UnitBridgeId implements Serializable {
private static final long serialVersionUID = 1L;
private int unit_master_id;
private int unit_slave_id;
public UnitBridgeId() {
}
public UnitBridgeId(int unit_master_id, int unit_slave_id) {
this.unit_master_id = unit_master_id;
this.unit_slave_id=unit_slave_id;
}
public int getUnit_master_id() {
return unit_master_id;
}
public void setUnit_master_id(int unit_master_id) {
this.unit_master_id = unit_master_id;
}
public int getUnit_slave_id() {
return unit_slave_id;
}
public void setUnit_slave_id(int unit_slave_id) {
this.unit_slave_id = unit_slave_id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + unit_master_id;
result = prime * result + unit_slave_id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UnitBridgeId other = (UnitBridgeId) obj;
if (unit_master_id != other.unit_master_id)
return false;
if (unit_slave_id != other.unit_slave_id)
return false;
return true;
}
@Override
public String toString() {
return "UnitBridgeId [unit_master_id=" + unit_master_id + ", unit_slave_id=" + unit_slave_id + "]";
}
}
我认为这是一个完美的例子,我们需要使用 @IdClass
注释,而不是 @Embeddable
作为组合键。
@Entity
@Table(name="unit")
public class Unit implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@Transient
private int parent_id;
@OneToMany(mappedBy = "unit_slave_id", cascade = CascadeType.ALL)
private Set<UnitBridge> childUnits = new HashSet<UnitBridge>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getParent_id() {
return parent_id;
}
public void setParent_id(int parent_id) {
this.parent_id = parent_id;
}
public Set<UnitBridge> getChildUnits() {
return childUnits;
}
public void setChildUnits(Set<UnitBridge> childUnits) {
this.childUnits = childUnits;
}
@Override
public String toString() {
return "Unit [id=" + id + ", name=" + name + ", parent_id=" + parent_id + "]";
}
public static void main(String[] args) {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Unit unit = new Unit();
unit.setName("A");
session.save(unit);
Set<UnitBridge> unitBridges = new HashSet<>();
{
UnitBridge unitBridge = new UnitBridge();
unitBridge.setUnit_master_id(100);
unitBridge.setUnit_slave_id(unit);
unitBridges.add(unitBridge);
}
{
UnitBridge unitBridge = new UnitBridge();
unitBridge.setUnit_master_id(200);
unitBridge.setUnit_slave_id(unit);
unitBridges.add(unitBridge);
}
unit.setChildUnits(unitBridges);
transaction.commit();
// Unit unit = session.get(Unit.class,1);
// System.out.println(unit.getId());
// System.out.println(unit.getChildUnits().iterator().next().getUnit_master_id());
session.close();
}
}
@Entity
@Table(name="unit_bridge")
@IdClass(UnitBridgeId.class)
public class UnitBridge implements Serializable{
private static final long serialVersionUID = 1L;
@Id
private int unit_master_id;
@ManyToOne
@Id
private Unit unit_slave_id;
public int getUnit_master_id() {
return unit_master_id;
}
public void setUnit_master_id(int unit_master_id) {
this.unit_master_id = unit_master_id;
}
public Unit getUnit_slave_id() {
return unit_slave_id;
}
public void setUnit_slave_id(Unit unit_slave_id) {
this.unit_slave_id = unit_slave_id;
}
}
public class UnitBridgeId implements Serializable {
private static final long serialVersionUID = 1L;
private int unit_master_id;
private Unit unit_slave_id;
public UnitBridgeId(){
}
public UnitBridgeId(int unit_master_id, Unit unit_slave_id) {
this.unit_master_id = unit_master_id;
this.unit_slave_id = unit_slave_id;
}
public int getUnit_master_id() {
return unit_master_id;
}
public void setUnit_master_id(int unit_master_id) {
this.unit_master_id = unit_master_id;
}
public Unit getUnit_slave_id() {
return unit_slave_id;
}
public void setUnit_slave_id(Unit unit_slave_id) {
this.unit_slave_id = unit_slave_id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UnitBridgeId that = (UnitBridgeId) o;
return unit_master_id == that.unit_master_id &&
Objects.equals(unit_slave_id, that.unit_slave_id);
}
@Override
public int hashCode() {
return Objects.hash(unit_master_id, unit_slave_id);
}
@Override
public String toString() {
return "UnitBridgeId [unit_master_id=" + unit_master_id + ", unit_slave_id=" + unit_slave_id + "]";
}
}
Hibernate 创建的表
Hibernate: create table unit (id integer not null, name varchar(255), primary key (id)) engine=MyISAM
Hibernate: create table unit_bridge (unit_master_id integer not null, unit_slave_id_id integer not null, primary key (unit_master_id, unit_slave_id_id)) engine=MyISAM
Hibernate: alter table unit_bridge add constraint FKgv4psic91eix7b780lekkrdg4 foreign key (unit_slave_id_id) references unit (id)
单位table
unit_bridge table
我的架构中有两个 table,它们之间存在一对多关系。
单位和unit_bridge
单元有 2 列 id 和 name
unit_bridge 有两列,unit_master_id 和 unit_slave_id。两者一起组成一个复合键。这里unit_slave_id是id[=55=的外键] 单位列。
当我收到 POST 请求时,正在创建一个名为 unit_child_units[=55 的新 table =] 在数据库中。并且 unit_bridge 正在更新为 unit_slave_id 列的错误值。 尽管 unit_master_id 的值在 unit_bridge table 中是正确的,但它对应的是 unit_slave_id 映射错了。
我不想要新的 table,而是想更新我的 unit_bridge table,因为我收到 POST用户请求 单位 table.
这是我的 json 请求,
{
"name" : "john doe",
"childUnits" : [
{
"unitBridgeId" :{
"unit_master_id" : 4
}
}
]
}
这是我的模型。
Unit.java
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Entity
@Table(name="unit")
@JsonInclude(Include.NON_NULL)
public class Unit implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@Transient
private int parent_id;
@OneToMany(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
private Set<UnitBridge> childUnits = new HashSet<UnitBridge>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getParent_id() {
return parent_id;
}
public void setParent_id(int parent_id) {
this.parent_id = parent_id;
}
public Set<UnitBridge> getChildUnits() {
return childUnits;
}
public void setChildUnits(Set<UnitBridge> childUnits) {
this.childUnits = childUnits;
}
@Override
public String toString() {
return "Unit [id=" + id + ", name=" + name + ", parent_id=" + parent_id + ", childUnits=" + childUnits + "]";
}
}
UnitBridge.java
import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Entity
@Table(name="unit_bridge")
@JsonInclude(Include.NON_NULL)
public class UnitBridge implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@EmbeddedId
private UnitBridgeId unitBridgeId;
@Override
public String toString() {
return "UnitBridge [unitBridgeId=" + unitBridgeId + "]";
}
public UnitBridgeId getUnitBridgeId() {
return unitBridgeId;
}
public void setUnitBridgeId(UnitBridgeId unitBridgeId) {
this.unitBridgeId = unitBridgeId;
}
public int getUnit_master_id() {
return unitBridgeId.getUnit_master_id();
}
public int getUnit_slave_id() {
return unitBridgeId.getUnit_slave_id();
}
public void setUnit_master_id(int unit_master_id) {
unitBridgeId.setUnit_master_id(unit_master_id);
}
public void setUnit_slave_id(int unit_slave_id) {
unitBridgeId.setUnit_slave_id(unit_slave_id);
}
}
UnitBridgeId.java
import java.io.Serializable;
import javax.persistence.Embeddable;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Embeddable
public class UnitBridgeId implements Serializable {
private static final long serialVersionUID = 1L;
private int unit_master_id;
private int unit_slave_id;
public UnitBridgeId() {
}
public UnitBridgeId(int unit_master_id, int unit_slave_id) {
this.unit_master_id = unit_master_id;
this.unit_slave_id=unit_slave_id;
}
public int getUnit_master_id() {
return unit_master_id;
}
public void setUnit_master_id(int unit_master_id) {
this.unit_master_id = unit_master_id;
}
public int getUnit_slave_id() {
return unit_slave_id;
}
public void setUnit_slave_id(int unit_slave_id) {
this.unit_slave_id = unit_slave_id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + unit_master_id;
result = prime * result + unit_slave_id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UnitBridgeId other = (UnitBridgeId) obj;
if (unit_master_id != other.unit_master_id)
return false;
if (unit_slave_id != other.unit_slave_id)
return false;
return true;
}
@Override
public String toString() {
return "UnitBridgeId [unit_master_id=" + unit_master_id + ", unit_slave_id=" + unit_slave_id + "]";
}
}
我认为这是一个完美的例子,我们需要使用 @IdClass
注释,而不是 @Embeddable
作为组合键。
@Entity
@Table(name="unit")
public class Unit implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@Transient
private int parent_id;
@OneToMany(mappedBy = "unit_slave_id", cascade = CascadeType.ALL)
private Set<UnitBridge> childUnits = new HashSet<UnitBridge>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getParent_id() {
return parent_id;
}
public void setParent_id(int parent_id) {
this.parent_id = parent_id;
}
public Set<UnitBridge> getChildUnits() {
return childUnits;
}
public void setChildUnits(Set<UnitBridge> childUnits) {
this.childUnits = childUnits;
}
@Override
public String toString() {
return "Unit [id=" + id + ", name=" + name + ", parent_id=" + parent_id + "]";
}
public static void main(String[] args) {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Unit unit = new Unit();
unit.setName("A");
session.save(unit);
Set<UnitBridge> unitBridges = new HashSet<>();
{
UnitBridge unitBridge = new UnitBridge();
unitBridge.setUnit_master_id(100);
unitBridge.setUnit_slave_id(unit);
unitBridges.add(unitBridge);
}
{
UnitBridge unitBridge = new UnitBridge();
unitBridge.setUnit_master_id(200);
unitBridge.setUnit_slave_id(unit);
unitBridges.add(unitBridge);
}
unit.setChildUnits(unitBridges);
transaction.commit();
// Unit unit = session.get(Unit.class,1);
// System.out.println(unit.getId());
// System.out.println(unit.getChildUnits().iterator().next().getUnit_master_id());
session.close();
}
}
@Entity
@Table(name="unit_bridge")
@IdClass(UnitBridgeId.class)
public class UnitBridge implements Serializable{
private static final long serialVersionUID = 1L;
@Id
private int unit_master_id;
@ManyToOne
@Id
private Unit unit_slave_id;
public int getUnit_master_id() {
return unit_master_id;
}
public void setUnit_master_id(int unit_master_id) {
this.unit_master_id = unit_master_id;
}
public Unit getUnit_slave_id() {
return unit_slave_id;
}
public void setUnit_slave_id(Unit unit_slave_id) {
this.unit_slave_id = unit_slave_id;
}
}
public class UnitBridgeId implements Serializable {
private static final long serialVersionUID = 1L;
private int unit_master_id;
private Unit unit_slave_id;
public UnitBridgeId(){
}
public UnitBridgeId(int unit_master_id, Unit unit_slave_id) {
this.unit_master_id = unit_master_id;
this.unit_slave_id = unit_slave_id;
}
public int getUnit_master_id() {
return unit_master_id;
}
public void setUnit_master_id(int unit_master_id) {
this.unit_master_id = unit_master_id;
}
public Unit getUnit_slave_id() {
return unit_slave_id;
}
public void setUnit_slave_id(Unit unit_slave_id) {
this.unit_slave_id = unit_slave_id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UnitBridgeId that = (UnitBridgeId) o;
return unit_master_id == that.unit_master_id &&
Objects.equals(unit_slave_id, that.unit_slave_id);
}
@Override
public int hashCode() {
return Objects.hash(unit_master_id, unit_slave_id);
}
@Override
public String toString() {
return "UnitBridgeId [unit_master_id=" + unit_master_id + ", unit_slave_id=" + unit_slave_id + "]";
}
}
Hibernate 创建的表
Hibernate: create table unit (id integer not null, name varchar(255), primary key (id)) engine=MyISAM
Hibernate: create table unit_bridge (unit_master_id integer not null, unit_slave_id_id integer not null, primary key (unit_master_id, unit_slave_id_id)) engine=MyISAM
Hibernate: alter table unit_bridge add constraint FKgv4psic91eix7b780lekkrdg4 foreign key (unit_slave_id_id) references unit (id)
单位table
unit_bridge table