我有一个基于springboot+hibernate+mysql的restapi,其中包含用于crud操作和数据检索的常用方法。模型中有几个多对多关系,我将展示我的问题的相关类:
pectest.java文件
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="idtest")
public class Pectest {
@Id
@GeneratedValue
@Column(name="idtest")
private int idtest=-1;
private String testname;
private String testdescription;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="idtesttype")
private Testtype testtype;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="iddatatype")
private Datatype datatype;
private String testurl;
private Date datecreated;
private Date lastupdated;
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(name = "test_checks_requisite",
joinColumns = @JoinColumn(name = "test_idtest"),
inverseJoinColumns = @JoinColumn(name = "requisite_idrequisite")
)
private Set<Requisite> requisites = new HashSet<Requisite>();
// Getters and setters
[...]
}
必需.java
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="idrequisite")
public class Requisite {
@Id
@GeneratedValue //(strategy=GenerationType.IDENTITY)
@Column(name="idrequisite")
private int idrequisite;
private String Name;
private String Title;
private String Description;
@ManyToOne(cascade = {CascadeType.PERSIST}, fetch=FetchType.LAZY)
@JoinColumn(name="functionality_idfunctionality")
private Functionality functionality;
@ManyToMany(mappedBy="requisites")
private Set<Pectest> tests = new HashSet<Pectest>();
// Getters and setters
[...]
}
这两种方法的get方法都按预期工作,正确地检索给定pectest的必需列表。然而,当我试图通过调用相应的api入口点来更新现有的pectest时,我发现它没有从db中获取json中的现有requisites,从而给它们一个idrequisite值0(如下所示)。因此,hibernate“决定”将它们作为新的插入。由于数据库中的唯一约束,它失败了,但问题是它们根本不应该被插入。
pectest对象的更新过程可能涉及(除了明显的名称、描述等修改)向其列表中添加更多必需的元素,但是这些元素在那时永远不会自己更新。
以下是所有额外信息:
传递给api的put方法的json数据示例
{
"idtest": 9,
"testtype": { "idTestType": 5, "testTypeName": "Manual" },
"datatype": null,
"requisites": [
{
"idrequisite": 2,
"functionality": {
"idfunctionality": 1002,
"functionalityName": "Data Access OPC-UA",
"parentFunctionality": {
"idfunctionality": 1000,
"functionalityName": "OPC-UA",
"parentFunctionality": null,
"childrenFunctionalities": [
{
"idfunctionality": 1006,
"functionalityName": "Alarmas OPC-UA",
"parentFunctionality": 1000,
"childrenFunctionalities": [],
"description": "Para el tratamiento de las Alarmas del producto BR, se utilizará el tipo propietario AlarmEventType, heredado del tipo básico de alarmas OffNormalAlarmType definido por la especificación OPC UA (Part 9). El Servidor OPC-UA deberá generar un nodo AlarmEventType para cada una de las alarmas definidas en el proyecto en concreto del producto BR (hasta 8192 alarmas distintas)."
},
{
"idfunctionality": 1001,
"functionalityName": "Atributos OPC-UA",
"parentFunctionality": 1000,
"childrenFunctionalities": [],
"description": "Atributos"
},
1002,
{
"idfunctionality": 1009,
"functionalityName": "Device Integration OPC-UA",
"parentFunctionality": 1000,
"childrenFunctionalities": [
{
"idfunctionality": 1011,
"functionalityName": "Tipo FieldDeviceType OPC-UA",
"parentFunctionality": 1009,
"childrenFunctionalities": [],
"description": "A partir del tipo estándar DeviceType definido por “OPC UA Device Integration” se crea el tipo propietario FieldDeviceType para representar e identificar al producto BR."
}
],
"description": "A partir del tipo estándar DeviceType definido por “OPC UA Device Integration” se crea el tipo propietario FieldDeviceType para representar e identificar al producto BR."
},
{
"idfunctionality": 1012,
"functionalityName": "Global Discovery Server OPC-UA",
"parentFunctionality": 1000,
"childrenFunctionalities": [],
"description": "El servidor OPC UA implementará el “Global Certificate Management Server Facet” para comunicarse con el GDS "
},
{
"idfunctionality": 1008,
"functionalityName": "Historical Access OPC-UA",
"parentFunctionality": 1000,
"childrenFunctionalities": [],
"description": "Esta funcionalidad es resuelta íntegramente por el Servidor OPC-UA, ya que el FW embebido no ofrece soporte para ella."
},
{
"idfunctionality": 1007,
"functionalityName": "Monitoring & Subscription OPC-UA",
"parentFunctionality": 1000,
"childrenFunctionalities": [],
"description": "Subscripciones para visualización de datos desde un cliente OPC-UA"
},
{
"idfunctionality": 1010,
"functionalityName": "Seguridad OPC-UA",
"parentFunctionality": 1000,
"childrenFunctionalities": [],
"description": "El servidor OPC-UA debe implementar una serie de medidas de seguridad para garantizar la confidencialidad de la información."
}
],
"description": "OPC-UA Server"
},
"childrenFunctionalities": [
{
"idfunctionality": 1004,
"functionalityName": "AnalogType OPC-UA",
"parentFunctionality": 1002,
"childrenFunctionalities": [],
"description": "Este tipo propietario se utiliza para los nodos OPC-UA de variables no booleanas del producto BR que no sean parámetros."
},
{
"idfunctionality": 1003,
"functionalityName": "DigitalType OPC-UA",
"parentFunctionality": 1002,
"childrenFunctionalities": [],
"description": "Tipo propietario de datos booleanos servido por OPC-UA, que no sean parámetros."
},
{
"idfunctionality": 1005,
"functionalityName": "ParameterType OPC-UA",
"parentFunctionality": 1002,
"childrenFunctionalities": [],
"description": "Este tipo propietario se utiliza para los nodos OPC-UA de variables del producto BR que estén identificadas como parámetros. El servidor OPC-UA debe identificar dichas variables del producto BR como aquellas que tengan atributo ParamGID. "
}
],
"description": "Se ofrecerá acceso a las variables exportadas por el FW de la CPU del producto BR a través de tres tipos propietarios de nodos: DigitalType, AnalogType y ParameterType"
},
"name": "REQ-0001",
"description": "Se ofrece acceso a variables digitales a través de este tipo de nodo",
"title": "Digital Type"
},
{
"idrequisite": 4,
"functionality": 1002,
"name": "REQ-0003",
"description": "Se ofrece acceso a parámetros a través de este tipo de nodo",
"title": "Parameter Type"
},
{
"idrequisite": 3,
"functionality": 1002,
"name": "REQ-0002",
"description": "Se ofrece acceso a variables analógicas a través de este tipo de nodo",
"title": "Analog Type"
}
],
"testDescription": "El servidor es capaz de devolver correctamente todos los tipos de dato.",
"testURL": "",
"testName": "Lectura de DataTypes",
"dateCreated": "09-05-2018 08:57:27",
"lastUpdated": "09-05-2018 08:57:27"
}
pectestcontroller.java文件
[...]
@PostMapping(path="/test", produces= MediaType.APPLICATION_JSON_VALUE)
public Pectest createOrUpdateTest(@Valid @RequestBody Pectest newtest) {
try {
System.out.println("Create or update Test: " + objectmapper.writeValueAsString(newtest));
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return testService.saveOrUpdate(newtest);
}
控制台输出(格式化)
{
"idtest": 9,
"testtype": { "idTestType": 5, "testTypeName": "Manual" },
"datatype": null,
"requisites": [
{
"idrequisite": 0,
"functionality": {
"idfunctionality": 0,
"functionalityName": "Data Access OPC-UA",
"parentFunctionality": {
"idfunctionality": 0,
"functionalityName": "OPC-UA",
"parentFunctionality": null,
"childrenFunctionalities": [
{
"idfunctionality": 0,
"functionalityName": "Device Integration OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [
{
"idfunctionality": 0,
"functionalityName": "Tipo FieldDeviceType OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "A partir del tipo estándar DeviceType definido por “OPC UA Device Integration” se crea el tipo propietario FieldDeviceType para representar e identificar al producto BR."
}
],
"description": "A partir del tipo estándar DeviceType definido por “OPC UA Device Integration” se crea el tipo propietario FieldDeviceType para representar e identificar al producto BR."
},
{
"idfunctionality": 0,
"functionalityName": "Historical Access OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "Esta funcionalidad es resuelta íntegramente por el Servidor OPC-UA, ya que el FW embebido no ofrece soporte para ella."
},
{
"idfunctionality": 0,
"functionalityName": "Atributos OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "Atributos"
},
{
"idfunctionality": 0,
"functionalityName": "Alarmas OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "Para el tratamiento de las Alarmas del producto BR, se utilizará el tipo propietario AlarmEventType, heredado del tipo básico de alarmas OffNormalAlarmType definido por la especificación OPC UA (Part 9). El Servidor OPC-UA deberá generar un nodo AlarmEventType para cada una de las alarmas definidas en el proyecto en concreto del producto BR (hasta 8192 alarmas distintas)."
},
0,
{
"idfunctionality": 0,
"functionalityName": "Monitoring & Subscription OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "Subscripciones para visualización de datos desde un cliente OPC-UA"
},
{
"idfunctionality": 0,
"functionalityName": "Seguridad OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "El servidor OPC-UA debe implementar una serie de medidas de seguridad para garantizar la confidencialidad de la información."
},
{
"idfunctionality": 0,
"functionalityName": "Global Discovery Server OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "El servidor OPC UA implementará el “Global Certificate Management Server Facet” para comunicarse con el GDS "
}
],
"description": "OPC-UA Server"
},
"childrenFunctionalities": [
{
"idfunctionality": 0,
"functionalityName": "ParameterType OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "Este tipo propietario se utiliza para los nodos OPC-UA de variables del producto BR que estén identificadas como parámetros. El servidor OPC-UA debe identificar dichas variables del producto BR como aquellas que tengan atributo ParamGID. "
},
{
"idfunctionality": 0,
"functionalityName": "DigitalType OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "Tipo propietario de datos booleanos servido por OPC-UA, que no sean parámetros."
},
{
"idfunctionality": 0,
"functionalityName": "AnalogType OPC-UA",
"parentFunctionality": 0,
"childrenFunctionalities": [],
"description": "Este tipo propietario se utiliza para los nodos OPC-UA de variables no booleanas del producto BR que no sean parámetros."
}
],
"description": "Se ofrecerá acceso a las variables exportadas por el FW de la CPU del producto BR a través de tres tipos propietarios de nodos: DigitalType, AnalogType y ParameterType"
},
"name": "REQ-0003",
"description": "Se ofrece acceso a parámetros a través de este tipo de nodo",
"title": "Parameter Type"
},
{
"idrequisite": 0,
"functionality": 0,
"name": "REQ-0002",
"description": "Se ofrece acceso a variables analógicas a través de este tipo de nodo",
"title": "Analog Type"
},
{
"idrequisite": 0,
"functionality": 0,
"name": "REQ-0001",
"description": "Se ofrece acceso a variables digitales a través de este tipo de nodo",
"title": "Digital Type"
}
],
"testDescription": "El servidor es capaz de devolver correctamente todos los tipos de dato.",
"testURL": "",
"testName": "Lectura de DataTypes",
"dateCreated": null,
"lastUpdated": null
}
如您所见,所有嵌套对象的id都为零。为什么hibernate不尝试检索这些元素?模型中是否缺少注解?
作为一种解决方法,我考虑在更新pectest时忽略必需对象的整个列表,并在api中提供一个单独的入口点,用于向将单独调用的测试添加必需对象。
我检查了这个线程,它指向这个例子,但是找不到解决方案。
1条答案
按热度按时间wribegjk1#
如果不希望自动生成ID,则应删除注解@generatedvalue。在您的例子中,您发送的是完整的对象(包括id),因此您不希望hibernate生成新的对象