Spring Java JPA 将 String 保存为 tinyblob,导致 json 解析错误
Posted
技术标签:
【中文标题】Spring Java JPA 将 String 保存为 tinyblob,导致 json 解析错误【英文标题】:Spring Java JPA is saving String as tinyblob, giving json parse error 【发布时间】:2021-09-28 19:09:05 【问题描述】:我有两个实体,具有一对一的关系。我希望一个做父母,另一个做孩子:
父级:MappingPayload,代码如下:
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "duplicate_handling_id", referencedColumnName = "id")
private DuplicateHandling duplicateHandling;
孩子:使用以下代码进行重复处理:
public MappingPayload()
this.id = null;
private String dupAction;
@OneToOne(mappedBy = "duplicateHandling")
private MappingPayload mappingPayload;
问题在于 DuplicateHandling 类中的私有字符串 dupAction。它作为 tinyblob 保存在 mysql 中,应该是 varchar。 (注意其他类中还有其他String字段被正确保存为varchar)
问题仅在于 DuplicateHandling 类,所以如果我添加更多字符串字段,它们也会保存为 tinyblob。我也尝试过手动更改数据库中的数据类型。
当我发送以下 json 时:
"mappingPayload":
"duplicateHandling": "dupAction":"we are"
我收到以下错误:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.sun.org.apache.xpath.internal.operations.String`
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('we are'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.sun.org.apache.xpath.internal.operations.String` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('we are')
at [Source: (PushbackInputStream); line: 3, column: 37] (through reference chain: com.amos.amosintegrationprocessor.requests.CreateMappingRequest["mappingPayload"]->com.amos.amosintegrationprocessor.entities.MappingPayload["duplicateHandling"]->com.amos.amosintegrationprocessor.entities.DuplicateHandling["dupAction"])]
这是来自 gradle 文件的版本信息:'org.springframework.boot' version '2.5.2'
【问题讨论】:
【参考方案1】:一个对象必须作为一个实体来引用。如果不这样做,jpa 会将其视为二进制,并将序列化的二进制放入数据库列中。
解决方案 1) 使其成为一个实体
简单地将其设为实体意味着使用 @Entity & Column 映射对其进行注释,从而生成一个新表
解决方案 2) 使其可嵌入
使用@Embeddable 注解代替@OneToOne 将使类的属性嵌套到父级的表表示中。
@Entity
public class MappingPayload
@Embedded
private DuplicateHandling duplicateHandling;
和
@Embeddable
public class DuplicateHandling
private String json;
这将导致 JPA 将 DuplicateHandling 中的列嵌套到 MappingPayload 中。这不是问题,因为它以前是 1:1 的关系。
永远记住,如果你将 DuplicateHandling 这样的复杂类型存储到数据库中而不告诉 JPA 如何存储它,它就会变成一个 blob。
可嵌入的技巧将使您的字符串保持不变。
一般提示:
如果您有结构化数据和关系数据库,请不要将 json 序列化为列,除非它们是真正需要的。如果您只有一个普通的类,则将其设置为新实体并引用它会更加通用。而且更干净。
【讨论】:
感谢您的评论。请注意,重复处理是一个实体,目前我已删除所有其他字段,但它将包含更多数据。不幸的是,所有字符串属性都给出了 json 解析错误并保存为 tinyblob。我认为我没有理解您的解决方案,如果您能详细说明,我将不胜感激。其次,第二个解决方案不起作用,Intelij 想让我删除它。我将 @Embaddable 放在父 MappingPayload 字段中的 privae DuplicateHandling duplicateHangling 对象之上。 请看示例 另外,您可能想检查一下baeldung.com/jpa-embedded-embeddable以上是关于Spring Java JPA 将 String 保存为 tinyblob,导致 json 解析错误的主要内容,如果未能解决你的问题,请参考以下文章
表单提交错误,无法将类型“java.lang.String”的值转换为浏览器中所需的类型错误,在 Spring MVC 中
JPA 将 java.io.File 或 java.nio.file.Path 对象映射到 STRING 列
使用 Spring Boot 和 JPA 将存储过程输出到 Java 自定义对象中