无法使用 Spring 使用 java REST Api 接收 json 数据

Posted

技术标签:

【中文标题】无法使用 Spring 使用 java REST Api 接收 json 数据【英文标题】:Cannot receive json data with java REST Api using Spring 【发布时间】:2019-08-10 06:53:27 【问题描述】:

我的数据库似乎连接正确,我还没有为我的其余应用程序包含所有类。我正在尝试解析这个 json 正文:

“名字”:“用户”, "姓氏":"用户", "电子邮件":"test@test.com", “密码”:“123”

使用HTTP POST 方法,但返回的是:


    "timestamp": "2019-03-19T16:20:01.121+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
    "path": "/users"


错误信息:

o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2019-03-19 12:19:50.892  INFO 25589 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2019-03-19 12:19:50.893  INFO 25589 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.16]
    2019-03-19 12:19:50.899  INFO 25589 --- [           main] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/vince/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
    2019-03-19 12:19:50.985  INFO 25589 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2019-03-19 12:19:50.986  INFO 25589 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1231 ms
    2019-03-19 12:19:51.102  INFO 25589 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
    2019-03-19 12:19:51.316  INFO 25589 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
    2019-03-19 12:19:51.356  INFO 25589 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
        name: default
        ...]
    2019-03-19 12:19:51.394  INFO 25589 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core 5.3.7.Final
    2019-03-19 12:19:51.395  INFO 25589 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
    2019-03-19 12:19:51.478  INFO 25589 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations 5.0.4.Final
    2019-03-19 12:19:51.558  INFO 25589 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.mysql5Dialect
    2019-03-19 12:19:51.949  INFO 25589 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
    2019-03-19 12:19:52.273  INFO 25589 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
    2019-03-19 12:19:52.299  WARN 25589 --- [           main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
    2019-03-19 12:19:52.432  INFO 25589 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2019-03-19 12:19:52.435  INFO 25589 --- [           main] c.v.app.ws.MobileAppWsApplication        : Started MobileAppWsApplication in 2.93 seconds (JVM running for 3.492)
    2019-03-19 12:20:00.945  INFO 25589 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
    2019-03-19 12:20:00.945  INFO 25589 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
    2019-03-19 12:20:00.950  INFO 25589 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 5 ms
    UserEntityid=0, userId='testId', firstName='null', lastName='null', email='null', encryptedPassword='test', emailVerificationToken='testing', emailVerificationStatus=false
    2019-03-19 12:20:01.091  WARN 25589 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1048, SQLState: 23000
    2019-03-19 12:20:01.091 ERROR 25589 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column 'encrypted_password' cannot be null
    2019-03-19 12:20:01.095 ERROR 25589 --- [nio-8080-exec-1] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
    2019-03-19 12:20:01.111 ERROR 25589 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

    java.sql.SQLIntegrityConstraintViolationException: Column 'encrypted_password' cannot be null
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.15.jar:8.0.15]
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.15.jar:8.0.15]


        [ . . .] 

我的 UserServiceImpl 类来帮助理解上下文:

package com.vincentaudette.app.ws.service.impl;

import com.vincentaudette.app.ws.UserRepository;
import com.vincentaudette.app.ws.io.entity.UserEntity;
import com.vincentaudette.app.ws.service.UserService;
import com.vincentaudette.app.ws.shared.dto.UserDto;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService 

    @Autowired
    UserRepository userRepository;

    @Override
    public UserDto createUser(UserDto userDto) 

        UserEntity userEntity = new UserEntity();

        userEntity.setEncryptedPassword("test");
        userEntity.setEmailVerificationToken("testing");
        userEntity.setUserId("testId");

        System.out.println(userEntity.toString());

        BeanUtils.copyProperties(userDto, userEntity);

        UserEntity storedUserDetails = userRepository.save(userEntity);

        UserDto returnDto = new UserDto();

        BeanUtils.copyProperties(storedUserDetails,returnDto);

        return returnDto;
   


package com.vincentaudette.app.ws;

import com.vincentaudette.app.ws.io.entity.UserEntity;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends CrudRepository<UserEntity, Long> 


package com.vincentaudette.app.ws.io.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.io.Serializable;

@Entity(name = "users")
public class UserEntity implements Serializable 

    private static final long serialVersionUID = 2L;

    @Id
    @GeneratedValue
    private long id;

    @Column(nullable = false)
    private String userId;

    @Column(nullable = false, length = 50)
    private String firstName;

    @Column(nullable = false, length = 50)
    private String lastName;

    @Column(nullable = false, length = 120, unique = true)
    private String email;

    @Column(nullable = false)
    private String encryptedPassword;

    private String emailVerificationToken;

    @Column(nullable = false)
    private Boolean emailVerificationStatus = false;

    public long getId() 
        return id;
    

    public void setId(long id) 
        this.id = id;
    

    public String getUserId() 
        return userId;
    

    public void setUserId(String userId) 
        this.userId = userId;
    

    public String getFirstName() 
        return firstName;
    

    public void setFirstName(String firstName) 
        this.firstName = firstName;
    

    public String getLastName() 
        return lastName;
    

    public void setLastName(String lastName) 
        this.lastName = lastName;
    

    public String getEmail() 
        return email;
    

    public void setEmail(String email) 
        this.email = email;
    

    public String getEncryptedPassword() 
        return encryptedPassword;
    

    public void setEncryptedPassword(String encryptedPassword) 
        this.encryptedPassword = encryptedPassword;
    

    public String getEmailVerificationToken() 
        return emailVerificationToken;
    

    public void setEmailVerificationToken(String emailVerificationToken) 
        this.emailVerificationToken = emailVerificationToken;
    

    public Boolean getEmailVerificationStatus() 
        return emailVerificationStatus;
    

    public void setEmailVerificationStatus(Boolean emailVerificationStatus) 
        this.emailVerificationStatus = emailVerificationStatus;
    

【问题讨论】:

您能否显示正在尝试执行插入操作的 SQL。我怀疑 col encrypted_pa​​ssword 有错字,或者 UseEntity 没有将 encrypted_pa​​ssword 映射到 setEncryptedPassword 请问您可以添加您的用户类吗? @haticeSigirci 我在上面加了两个 【参考方案1】:

我不确切知道您使用的是什么技术,但似乎 hibernate 配置为使用 undersore 命名。因此,您将“encryptedPassword”列发送到期望“encrypted_pa​​ssword”的数据库。

由于此列不为空,因此会引发错误。

在这里查看this answer。

【讨论】:

【参考方案2】:

我通过从 userDto 复制属性后设置属性来解决:

UserEntity userEntity = new UserEntity();
BeanUtils.copyProperties(userDto, userEntity);

userEntity.setEncryptedPassword("test");
userEntity.setEmailVerificationToken("testing");
userEntity.setUserId("testId");

【讨论】:

以上是关于无法使用 Spring 使用 java REST Api 接收 json 数据的主要内容,如果未能解决你的问题,请参考以下文章

当登录尝试超过 3 次时,用户无法使用 Spring Security Rest API 登录?

使用 Spring Boot 创建 REST API [重复]

无法使用 Spring Boot 自动配置访问 REST 控制器

使用 restAssured 测试 Spring Boot Rest 应用程序

Spring 4 REST Web 服务无法使用安全性

使用带有 Spring Boot 的 Spock 测试框架来测试我的 REST 控制器