我有以下实体类:
@Entity
@Table(name="reporteddevicedata", schema="schemaName")
public class MobileDeviceData {
@EmbeddedId
MobileDeviceDataId mobileDeviceDataId;
@Column(name="activitydetecteddate")
private ZonedDateTime activityDetectedDate;
public void setFlagId(int flagId) {
mobileDeviceDataId.setFlagId(flagId);
}
......
}
@Embeddable
class MobileDeviceDataId implements Serializable {
@Column(name="clientid")
private int clientId;
@Column(name="flagid")
private int flagId;
}
我的Controller
代码如下所示:
@RequestMapping(value="/mobile/device", method = RequestMethod.PUT)
public ResponseEntity<Object> flagDevice (@RequestBody List<MobileDeviceData> deviceInfoList) {
// code here
}
最初,我的 Entity
类在 clientId
上只有一个主键 @ID
,而且效果很好。我将进行 REST 调用,它将按预期填充 MobileDeviceData 类。然后,我使用 @Embeddable
和 @EmbeddableId
注释切换到复合 ID,现在 @RequestMapping
无法填充 flagId
参数。现在,当我进行 REST 调用时,我收到 mobileDeviceDataId
的空指针异常,因此在调用该字段时无法更新该字段并引发空指针异常。
所以我的问题是,如何获取 @Embeddable
类的实例?我可以只使用 new
创建一个吗?我不确定这意味着什么,因为 Spring 可能期望自己实现这个值?通过 RequestMapping
更新此字段的“正常”方式是什么?
最佳答案
首先你应该避免嵌入 id,它只会让事情变得更困难
代理主键更容易使用,当您在具有多列主键的表上有外键时,它会使处理变得更加复杂
现在您自己面临这些问题,但根据您的问题
@RequestMapping(value="/mobile/device", method = RequestMethod.PUT)
public ResponseEntity<Object> flagDevice (@RequestBody List<MobileDeviceData> deviceInfoList) {
for(MobileDeviceData mobileDeviceData : deviceInfoList){
int clientId = mobileDeviceData.getMobileDeviceDataId().getClientId();
int flagId = mobileDeviceData.getMobileDeviceDataId().getFlagId();
MobileDeviceData foundMobileDeviceData = mobileDeviceDataService.findByClientIdAndFlagId(clientId, flagId);
if(foundMovileDeviceData == null){
mobileDeviceDataService.save(mobileDeviceData);
}else {
//update foundMobileDeviceData with mobileDeviceData fields
mobileDeviceDataService.save(foundMobileDeviceData);
}
}
}
否则,如果您只想更新标记 ID
@RequestMapping(value="/mobile/device", method = RequestMethod.PUT)
public ResponseEntity<Object> flagDevice (@RequestBody List<MobileDeviceData> deviceInfoList) {
for(MobileDeviceData mobileDeviceData : deviceInfoList){
int clientId = mobileDeviceData.getMobileDeviceDataId().getClientId();
MobileDeviceData foundMobileDeviceData = mobileDeviceDataService.findByClientId(clientId);
if(foundMovileDeviceData == null){
mobileDeviceDataService.save(mobileDeviceData);
}else {
//update foundMobileDeviceData with mobileDeviceData
int flagId = foundMobileDeviceData.getMobileDeviceDataId().getFlagId();
MobileDeviceDataId mobileDeviceDataId = foundMobileDeviceData.getMobileDeviceDataId();
mobileDeviceDataId.setFlagId(mobileDeviceData)
mobileDeviceDataService.save(foundMobileDeviceData);
}
}
}
接下来,如果您想通过客户端 ID 查找某些内容,只需创建一个 JPA 查询,例如
"from MobileDeviceData WHERE mobileDeviceDataId.clientId = :clientId"
或 native sql
"SELECT * FROM reporteddevicedata WHERE client_id = :someParam"
示例 JSON 请求
[ {
"mobileDeviceDataId" : {
"clientId" : 0,
"flagId" : 0
},
"activityDetectedDate" : null
}, {
"mobileDeviceDataId" : {
"clientId" : 1,
"flagId" : 1
},
"activityDetectedDate" : null
}, {
"mobileDeviceDataId" : {
"clientId" : 2,
"flagId" : 2
},
"activityDetectedDate" : null
} ]
丑陋的准备复制/粘贴版本:
[{"mobileDeviceDataId":{"clientId":0,"flagId":3},"activityDetectedDate":null},{"mobileDeviceDataId":{"clientId":1,"flagId":1},"activityDetectedDate":null},{"mobileDeviceDataId":{"clientId":2,"flagId":2},"activityDetectedDate":null}]
此外,您的 MobileData 对象上应该添加一些验证,以避免发送无效 json 请求时出现空指针(不存在 mobileDeviceDataId)
终于回答问题了:
使用数据库模型作为容器在 API 之间共享并不是一个好的做法(因为主键,可能是一些敏感数据,这取决于情况)。
此外,如果您希望 embeddableId 正常工作,则必须像示例 json 中那样构建请求。必须填写正确的字段。当请求不是以这种方式构建并且它们只是没有“嵌入 id”的平面 json 时,您必须创建一些适合 json 格式的包装器(此包装器将是 requestbody 类或列表)。接下来,您必须将包装器转换为带有嵌入式 id 的数据库对象(使用 new 关键字创建)。 这就是为什么我建议您不要使用复合或嵌入式 id。这是一个简单的例子,你只有一个表,但是当涉及到使用外键和多列主键时,表变得更加复杂和困惑,你使数据库搜索变得更加困难,这就是为什么我建议你使用代理ID而不嵌入任何东西,这让事情变得更困难而且很困惑
关于java - RequestMapping 无法填充实体类,其中 EmbeddedId 中的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33685029/