Spring Data CrudRepository的save方法抛出了InvocationTargetException。

3

我花了整个周末试图调试这段代码。我有一个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请求:

Postman

我从哪里获取以下内容

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

我调试过程中遇到了 InvocationTargetException 错误,如下所示: 这是控制器,在 save() 函数之前,似乎抛出了异常: Controller state before catch

以下为异常捕获代码:

enter image description here 我发现这篇文章在StackOverflow的一个类似事件上发布,但我认为这种情况并不是发生在我目前只有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

我希望能得到任何有关编程的想法。感谢您抽出时间。


1
你能包含堆栈跟踪吗? - hamid
will be my pleasure - Tsakiroglou Fotis
1
你有一个id字段,它没有分配生成器。因此,在保存对象之前,您需要更改该字段或手动分配一个id - M. Deinum
1
耶稣。我怎么错过了那个?@M.Deinum 就是那个 (@GeneratedValue(strategy = GenerationType.SEQUENCE)),请随意创建一个答案并获得积分。你非常值得。此外,由于这个异常似乎有点误导性,我将保留这个问题。 - Tsakiroglou Fotis
1个回答

2
如果您查看最后一张截图,您会看到一条消息,指示存在一个没有值的id字段。
在您的实体中,您声明了以下的id字段:
@Id
@Column(name = "business_id", nullable = false)
private Long id;

这表明Hibernate不应该生成一个键,或者没有分配数据库。这意味着您需要手动设置id的值。如果您不这样做,就会遇到此异常。

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接