Spring Data CrudRepository 的保存抛出 InvocationTargetException

Spring Data CrudRepository's save throws InvocationTargetException

我整个周末都在调试这段代码。我有一个 Spring RestController :

import com.tsakirogf.schedu.model.ContactMean;
import com.tsakirogf.schedu.model.DefaultContactMean;
import com.tsakirogf.schedu.model.human.Business;
import com.tsakirogf.schedu.services.BusinessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;
import java.util.Set;

@RestController
@RequestMapping("api/v1/business/")
public class BusinessController
{
    @Autowired
    BusinessService businessService;

    @GetMapping(value = "businesss")
    Iterable<Business> list()
    {
        Iterable<Business> retVal = businessService.findAll();
        return retVal;
    }

    @RequestMapping(value = "business", method = RequestMethod.POST,  consumes = MediaType.APPLICATION_JSON_VALUE)
    Business create(@RequestBody Business business)
    {
        CollectionOfContactMethods collectionOfContact = business.getContact();
        collectionOfContact.setBusiness(business);
        Set<ContactMean> contactMeanSet = collectionOfContact.getContactMeans();
        DefaultContactMean defaultContactMeanSet = collectionOfContact.getDefaultContactMean();
        defaultContactMeanSet.getCollectionOfContactMethodsDefault().setId(collectionOfContact.getId());
        for (ContactMean element : contactMeanSet)
        {
            element.setCollectionOfContactMethods(collectionOfContact);
        }
        collectionOfContact.setDefaultContactMean(defaultContactMeanSet);
        business.setContact(collectionOfContact);

        Business retval = businessService.save(business);
        return retval;
    }

    @RequestMapping(value = "business/{id}",  method = RequestMethod.GET )
    Optional<Business> get(@PathVariable Long id)
    {
        return businessService.findById(id);
    }
}

和服务:


public interface BusinessService extends CrudRepository<Business, Long>
{
}

这是模型:

@Table(name = "business")
public class Business
{
    @Id
    @Column(name = "business_id", nullable = false)
    private Long id;

    @JsonProperty("name")
    private String name;

    @Embedded
    @JsonProperty("address")
    private Address address;

    @OneToMany(mappedBy = "business",
        cascade = CascadeType.ALL,
        fetch = FetchType.LAZY)
    @JsonProperty("operatives")
    @JsonIgnore
    Set<Professional> operatives;

    @OneToOne(mappedBy = "business",
        cascade = CascadeType.ALL,
        fetch = FetchType.LAZY,
        optional = false)
    @JsonBackReference
    @JsonProperty("contact_numbers")
    private CollectionOfContactMethods contact;

    public Business()
    {
    }

    // Getters and Setters
}

当我发送这样的 POST 请求时:

我从哪里得到以下内容

{ "timestamp": "2021-11-01T08:59:06.343+00:00", "status": 500, "error": "Internal Server Error", "path": "/api/v1/business/business" }

我调试并得到 InvocationTargetException 如下所示 这是控制器,就在 save() 之前,它似乎抛出:

关键是:

我在 Whosebug 中找到了 this article posted in a ,但我认为这不是这种情况,因为我现在只有 H2 数据库。 这是 application.properties 个文件:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.hbm2ddl.auto=create

如果有任何想法,我将不胜感激。感谢您的宝贵时间。

如果您查看上一个屏幕截图,您会看到一条消息,指出 id 字段没有值。

在您的实体中,您的 id 字段有以下声明:

@Id
@Column(name = "business_id", nullable = false)
private Long id;

这表明休眠不应该生成密钥,或者没有数据库分配密钥。这意味着您需要手动设置 id 的值。如果不这样做,您将 运行 进入此异常。

现在我假设这是一个错误,您实际上想要一个序列或自动递增的 id 字段。为此添加 @GeneratedValue 注释以添加此行为。

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE))
@Column(name = "business_id", nullable = false)
private Long id;

这将指示 hibernate 在插入实体时使用序列生成 id。如果您的数据库支持 identity 列,您可能希望使用 GenerationType.IDENTITY 而不是 GenerationType.SEQUENCE