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
。
我整个周末都在调试这段代码。我有一个 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
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
。