Dan*_*own 21 java orm hibernate jpa hibernate-mapping
我有两个实体如下,当我尝试将项目添加到我的汽车表时,它显示以下错误消息;因此,它不允许我有多个汽车进行'自动'传输.
错误:
#1062 - Duplicate entry 'Auto' for key 'UK_bca5dfkfd4fjdhfh4ddirfhdhesr'
Run Code Online (Sandbox Code Playgroud)
实体:
汽车
@Entity
public class Car implements java.io.Serializable {
@Id
@GeneratedValue
long id;
@Column(name="transmission", nullable = false)
String transmission;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "car")
Set<CarFactory> factories;
...
}
Run Code Online (Sandbox Code Playgroud)
汽车表的样本值:
10 Auto
12 Auto
43 Manual
54 Manual
65 Normal
68 Standard
90 Normal
99 NoGear
Run Code Online (Sandbox Code Playgroud)
CarFactory
@Entity
public class CarFactory implements java.io.Serializable {
@Id
@JoinColumn(name="transmission",referencedColumnName = "transmission")
@ManyToOne
Car car;
@Id
@JoinColumn(name="factory_id", referencedColumnName= "id")
@ManyToOne
Factory factory;
...
}
Run Code Online (Sandbox Code Playgroud)
CarFactory表的预期值
Auto Fac1
Auto Fac2
Manual Fac1
Auto Fac5
Standard Fac6
Normal Fac3
NoGear Fac1
Run Code Online (Sandbox Code Playgroud)
我也回答了这个问题,但它没有奏效.
长话短说,我需要有一个表,其中包含来自其他表的两个外键,并带有组合主键.它不应该在参与表中强制使用唯一的外键.
我模仿了你的用例,你可以在GitHub上找到测试.
这些是映射:
@Entity(name = "Car")
public static class Car implements Serializable {
@Id
@GeneratedValue
long id;
@Column(name="transmission", nullable = false)
String transmission;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "car")
Set<CarFactory> factories;
}
@Entity(name = "Factory")
public static class Factory implements Serializable {
@Id
@GeneratedValue
long id;
}
@Entity(name = "CarFactory")
public static class CarFactory implements Serializable {
@Id
@ManyToOne
@JoinColumn(name = "transmission", referencedColumnName = "transmission")
Car car;
@ManyToOne
@Id
Factory factory;
public void setCar(Car car) {
this.car = car;
}
public void setFactory(Factory factory) {
this.factory = factory;
}
}
Run Code Online (Sandbox Code Playgroud)
这是您添加一些测试数据的方式:
doInTransaction(session -> {
Car car = new Car();
car.transmission = "Auto";
Car car1 = new Car();
car1.transmission = "Manual";
Factory factory = new Factory();
session.persist(factory);
session.persist(car);
session.persist(car1);
CarFactory carFactory = new CarFactory();
carFactory.setCar(car);
carFactory.setFactory(factory);
CarFactory carFactory1 = new CarFactory();
carFactory1.setCar(car1);
carFactory1.setFactory(factory);
session.persist(carFactory);
session.persist(carFactory1);
});
Run Code Online (Sandbox Code Playgroud)
测试工作正常:
@Test
public void test() {
doInTransaction(session -> {
List<CarFactory> carFactoryList = session.createQuery("from CarFactory").list();
assertEquals(2, carFactoryList.size());
});
}
Run Code Online (Sandbox Code Playgroud)
由于以下唯一约束,您会收到异常:
alter table Car add constraint UK_iufgc8so6uw3pnyih5s6lawiv unique (transmission)
Run Code Online (Sandbox Code Playgroud)
这是正常行为,因为FK必须唯一地标识PK行.就像你不能有更多具有相同PK的行一样,你不能有一个FK标识符引用多于一行.
你映射是个问题.你需要引用别的东西,而不是transmision.您需要一个唯一的汽车标识符,如VIN(车辆识别号),因此您的映射将变为:
@Entity(name = "Car")
public static class Car implements Serializable {
@Id
@GeneratedValue
long id;
@Column(name="vin", nullable = false)
String vin;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "car")
Set<CarFactory> factories;
}
@Entity(name = "CarFactory")
public static class CarFactory implements Serializable {
@Id
@ManyToOne
@JoinColumn(name = "vin", referencedColumnName = "vin")
Car car;
@ManyToOne
@Id
Factory factory;
public void setCar(Car car) {
this.car = car;
}
public void setFactory(Factory factory) {
this.factory = factory;
}
}
Run Code Online (Sandbox Code Playgroud)
这样,它vin是唯一的,并且子关联可以引用一个且仅一个父代.
这里的问题是你使用非主键字段作为外键似乎是不正确的,你的transmission字段应该是唯一的,这一行不正确:
@JoinColumn(name="transmission",referencedColumnName = "transmission")
Run Code Online (Sandbox Code Playgroud)
你有一个Many-To-Many映射,在关联表中需要一个@EmbeddedId属性,你的代码应该是这样的:
CarFactory类
@Entity
public class CarFactory {
private CarFactoryId carFactoryId = new CarFactoryId();
@EmbeddedId
public CarFactoryId getCarFactoryId() {
return carFactoryId;
}
public void setCarFactoryId(CarFactoryId carFactoryId) {
this.carFactoryId = carFactoryId;
}
Car car;
Factory factory;
//getters and setters for car and factory
}
Run Code Online (Sandbox Code Playgroud)
CarFactoryId类
@Embeddable
public class CarFactoryId implements Serializable{
private static final long serialVersionUID = -7261887879839337877L;
private Car car;
private Factory factory;
@ManyToOne
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@ManyToOne
public Factory getFactory() {
return factory;
}
public void setFactory(Factory factory) {
this.factory = factory;
}
public CarFactoryId(Car car, Factory factory) {
this.car = car;
this.factory = factory;
}
public CarFactoryId() {}
}
Run Code Online (Sandbox Code Playgroud)
汽车课
@Entity
public class Car {
@Id
@GeneratedValue
long id;
@Column(name="transmission", nullable = false)
String transmission;
private Set<CarFactory> carFactories = new HashSet<CarFactory>();
@OneToMany(mappedBy = "primaryKey.car",
cascade = CascadeType.ALL)
public Set<CarFactory> getCarFactories() {
return carFactories;
}
...
Run Code Online (Sandbox Code Playgroud)
}
对于Factory类来说同样的事情,请注意有几种方法来定义embedded id或者a composite id,看看:
注意:
在我的示例中,我没有transmission在复合ID中使用字段,但您可以使用它,您可以看到以下示例:
| 归档时间: |
|
| 查看次数: |
931 次 |
| 最近记录: |