@Transactional
它本身应该反映对数据库中的实体所做的更改。我正在创建一个应用程序,客户机可以在其中创建一个像这样的car实体( update
方法是以后用的放,不注意了 brand
属性):
@Entity
@Table(name = "cars")
public class Car {
@Id
@GeneratedValue(generator = "inc")
@GenericGenerator(name = "inc", strategy = "increment")
private int id;
@NotBlank(message = "car name`s must be not empty")
private String name;
private LocalDateTime productionYear;
private boolean tested;
public Car() {
}
public Car(@NotBlank(message = "car name`s must be not empty") String name, LocalDateTime productionYear) {
this.name = name;
this.productionYear = productionYear;
}
@ManyToOne
@JoinColumn(name = "brand_id")
private Brand brand;
public int getId() {
return id;
}
void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDateTime getProductionYear() {
return productionYear;
}
public void setProductionYear(LocalDateTime productionYear) {
this.productionYear = productionYear;
}
public boolean isTested() {
return tested;
}
public void setTested(boolean tested) {
this.tested = tested;
}
public Brand getBrand() {
return brand;
}
void setBrand(Brand brand) {
this.brand = brand;
}
public Car update(final Car source) {
this.productionYear = source.productionYear;
this.brand = source.brand;
this.tested = source.tested;
this.name = source.name;
return this;
}
}
在我的应用程序中,客户机可以使用put方法创建一辆新车或更新一辆现有的车。
我的控制器:
@RestController
public class CarController {
private Logger logger = LoggerFactory.getLogger(CarController.class);
private CarRepository repository;
public CarController(CarRepository repository) {
this.repository = repository;
}
//The client can create a new resource or update an existing one via PUT
@Transactional
@PutMapping("/cars/{id}")
ResponseEntity<?> updateCar(@PathVariable int id, @Valid @RequestBody Car source) {
//update
if(repository.existsById(id)) {
repository.findById(id).ifPresent(car -> {
car.update(source); //it doesn`t work
//Snippet below works
//var updated = car.update(source);
//repository.save(updated);
});
return ResponseEntity.noContent().build();
}
//create
else {
var result = repository.save(source);
return ResponseEntity.created(URI.create("/" + id)).body(result);
}
}
}
当我创造一辆新车时,它是有效的。但是,如代码中所述,当没有save方法时,尽管我得到了状态204(无内容),但实体没有更改。如果有save方法,它就可以正常工作。你知道为什么会这样吗?
其中一个用户向我请求 Brand
实体。我没有创造任何 Brand
但本质上 Car
可以属于特定的 Brand
在我的应用程序中。到目前为止,还没有 Car
属于任何 Brand
. 这是一个实体:
@Entity
@Table(name = "brands")
public class Brand {
@Id
@GeneratedValue(generator = "i")
@GenericGenerator(name = "i", strategy = "increment")
private int id;
@NotBlank(message = "brand name`s must be not empty")
private String name;
private LocalDateTime productionBrandYear;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "brand")
private Set<Car> cars;
@ManyToOne
@JoinColumn(name = "factory_id")
private Factory factory;
public Brand() {
}
public int getId() {
return id;
}
void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDateTime getProductionBrandYear() {
return productionBrandYear;
}
public void setProductionBrandYear(LocalDateTime productionBrandYear) {
this.productionBrandYear = productionBrandYear;
}
public Set<Car> getCars() {
return cars;
}
public void setCars(Set<Car> cars) {
this.cars = cars;
}
public Factory getFactory() {
return factory;
}
public void setFactory(Factory factory) {
this.factory = factory;
}
}
2条答案
按热度按时间ttcibm8c1#
我在本地用相同的用例测试了您的实体,发现一切都正常工作,我在这里写下我的发现和配置,这样您就可以验证您出了什么问题。
所以,当我发出put呼叫时
id
但是Car
实体不存在于表中,它被创建并且我收到201响应(我猜您得到的是相同的)您可以看到值为的行也被插入到表中
这些是打印出来的查询日志
现在,让我们来更新相同的实体,当发出相同的put请求时
id
对于更改的值,请注意表中的值将更改,并更新日志中的查询您可以看到,对于空的body得到了相同的204响应,让我们看看表条目
因此,这些更改反映在db中,让我们看看此操作的sql日志
所以,我不确定,你们是如何验证的,你们验证了什么,但你们的实体必须工作,我使用了和你们相同的控制器功能
与源代码的可能差异如下:
我曾经
IDENTITY
生成器来生成主键,而不是实体上的主键,因为这对我来说很容易测试。我提供了objectmapperbean来序列化/反序列化请求主体
Car
对象以支持Java8LocalDateTime
转换时,您可能有发送日期时间值的方法,以便它转换为Car
对象。然而,这些差异并不重要。
application.properties打印查询日志以验证是否触发了查询
qaxu7uf22#
更新car对象并不意味着它会更新db中的值。您始终需要调用repository.save()方法将更改持久化到数据库中。