Hibernate AutoGenerated 值不适用于 Jackson 映射器

Posted

技术标签:

【中文标题】Hibernate AutoGenerated 值不适用于 Jackson 映射器【英文标题】:Hibernate AutoGenerated value not working with Jackson mapper 【发布时间】:2018-02-18 00:47:57 【问题描述】:

我刚开始使用 Spring Boot CrudRepository,现在我的实体有一个具有自动生成值的唯一字段(不是 P.K)FeedID。 当我手动创建一个新对象而不设置 FeedID 值时,它工作正常,FeedID 自动生成。 但是当我使用 JackSon 对象映射器将请求参数 Json 直接转换为 pojo 对象时,它显示 FeedID 字段的空/重复异常。

控制器

@RequestMapping(method=RequestMethod.POST,value="/feed/addNewFeed")
public Feed addNewFeed(@RequestParam("Feed") String jsonFeed) throws JsonParseException, JsonMappingException, IOException  
    Feed feed = new ObjectMapper().readValue(jsonFeed, Feed.class);         
    return feedRepoImplementation.addNewFeedImpl(feed);     

实体

@GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, unique = true)
    private int FEED_ID;
    @Id
    @Column(length=100)
    private String URL_LINK;//Primary Key
    private String HEADLINE;
    @Column(length=1500,nullable=false)
    private String CONTENT;
    @Column(length=500,nullable=false)
    private String HEADLINE_IMAGE;  
    private FeedCatagory CATAGORY;
    private String AUTHOUR_NAME;
    private String PUBLISHING_DATE; 
    private String PUBLISHED;
    private int VIEWS;
    private int SHARED;

错误

  com.microsoft.sqlserver.jdbc.SQLServerException: Violation of UNIQUE KEY constraint 'UK_6hu52poark0i0f4us9cfql8au'. Cannot insert duplicate key in object 'dbo.feed'.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) ~[sqljdbc4.jar:na]
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515) ~[sqljdbc4.jar:na]
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404) ~[sqljdbc4.jar:na]
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350) ~[sqljdbc4.jar:na]
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696) ~[sqljdbc4.jar:na]

但是如果我手动创建 pojo 而不是使用 Objectmapper 而不触及 FeedID 字段,它可以正常工作

    Feed feed = new Feed();
    feed.setAUTHOUR_NAME("AUTHOUR");
    feed.setCATAGORY(UtilityHelper.FeedCatagory.SPORTS);
    feed.setPUBLISHING_DATE("12/10/16");
    feed.setCONTENT("CONTENT");
    feed.setURL_LINK("URL-LINK");
    feed.setHEADLINE("HEADLINE");
    feed.setPUBLISHED("TRUE");
    feed.setSHARED(0);
    feed.setVIEWS(0);
    feedRepository.save(feed);

我猜在客户端 JSON 中我没有包含自动生成的字段 'FeedID' ,因此 obectMapper 自动为该字段分配 0 ,但由于 0 已经存在所以重复约束显示。请帮忙

【问题讨论】:

如果我在 json 中传递 "feedID":nul 它会显示空指针, 您的代码也将 ID 保留为其默认值:0。为什么不使用调试器查看 JSON 包含哪些值,以及您的 ID 包含哪些值?另外,为什么不尊重 Java 命名约定,为什么将 JSON 作为请求参数发送,而不是直接作为请求正文发送? @Chanky 。您是否尝试过带空格的 feedID:feedID:"" 【参考方案1】:

使用@RequestBody 注释而不是@RequestParam 并从您的前端或邮递员发送JSON,因此无需使用ObjectMapper 将字符串转换为对象。

@RequestMapping(value="/feed/addNewFeed",method=RequestMethod.POST)
public Feed addNewFeed(@RequestBody Feed feed)     
    return feedRepoImplementation.addNewFeedImpl(feed);     

您还使用 @GeneratedValue 和您的 FEED_ID 字段。 @GeneratedValue 如果与@Id 一起使用,将创建唯一编号。

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false, unique = true)
    private int FEED_ID;

由于您已经有 @Id 注释字段,如果您手动生成唯一编号到 FEED_ID 会更好。为此,您必须在实体类中使用 @PrePersist 注释,如下所示:

@PrePersist
public void initializeFeedId() 
    Random random = new Random(System.currentTimeMillis());
    this.FEED_ID = random.nextInt(1000000000);

这将根据当前时间生成唯一编号。

【讨论】:

使用 RequestBody 更改了 RequestMapping ,并使用 POSTMAN 的 body 选项发送 JSON 数据,但是没有运气,同样的事情发生了,img42.com/mH27W 能否提供完整的堆栈跟踪 您使用的是哪个数据库? SQL 服务器。我注意到了一些事情,现在我将 URL_LINK 作为 PK,将 FEED_ID 作为 AutoGenerate 唯一整数列,如果我使用 AutoGenerate 将 FEED_ID 作为 PK,那么它工作顺利,否则无论 AutoGenerate 为何,FeedID 始终为“0”,请参阅休眠日志@987654322 的详细信息@ 太棒了,这个“@PrePersist”成功了,实际上我不知道如果不与 Id 注释一起使用 GeneratedValue 不起作用,很抱歉浪费您的时间,非常感谢。跨度>

以上是关于Hibernate AutoGenerated 值不适用于 Jackson 映射器的主要内容,如果未能解决你的问题,请参考以下文章

PMD - Avoid autogenerated methods to access private fields and methods of inner / outer classes(示例代码

u-boot使用make编译出现找不到dtc命令,如何解决啊

将右值引用绑定到(自动生成的)左值

编译第一步 make xxx_defconfig——Makefile.build 脚本

JPA/Hibernate:如何为 @ManyToOne 插入默认值,其中值表示空条目

Hibernate 更新某个值