使用 spring-data-jpa 保存新条目
Saving new entry with spring-data-jpa
我有一个带有一些默认列值的 MySQL table 和 RestController。
当我 POST 到 /orders 端点时,我发送一个 JSON 对象,我得到一个响应,其中包含我已发送的信息 + MySQL 条目的自动生成的 ID。
我该怎么做才能使请求 return 成为已保存在数据库中的完整条目,包括默认列值?我知道,我在响应中获得的 ID,我可以用它来发出 GET 请求以检索所有数据,但我不想发出新请求。
MySQL 订单 table
`ID` int NOT NULL AUTO_INCREMENT,
`order_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`delivery_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
订单模型
@Entity
@Table(name="orders")
@Getter @Setter @DynamicUpdate @DynamicInsert
public class OrderModel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ID")
private Integer id;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="order_date")
Date orderDate;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="delivery_date")
Date deliveryDate;
protected OrderModel() {}
}
Spring RestController
@RestController
@AllArgsConstructor
@RequestMapping("orders")
public class OrdersController {
private final OrdersRepository ordersRepo;
@ResponseBody
@PostMapping
public OrderModel addOrder(@RequestBody OrderModel order) {
return ordersRepo.saveAndFlush(order);
}
}
POST 请求正文:
{}
POST 响应正文:
{
"id":40,
"orderDate":null,
"deliveryDate":null
}
一个可能的解决方案是仅在您需要的地方使用 EntityManager 的 refresh(Object entity) 方法对您要保存在数据库中的实体并获取它回来了。
另一种解决方案是在 存储库基础 class 中使用相同的 refresh(Object entity) 方法来实现全局且不更改任何其他内容,如下所示:
- 创建一个新的自定义 存储库基础 class 以覆盖 save 方法。 (包括刷新(对象实体))
- 让 spring-boot 知道您希望它使用您刚刚创建的自定义存储库基础 class。
- 现在,当您调用存储库的 save() 方法时,它将使用您在存储库基础中创建的方法 class。
public class CustomBaseRepository<T, ID> extends SimpleJpaRepository<T, ID> {
private final EntityManager entityManager;
private final JpaEntityInformation<T, ?> entityInformation;
CustomBaseRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
this.entityInformation = entityInformation;
}
@Transactional
@Override
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
entityManager.persist(entity);
//the next line of code saves the entry in the database for real and updates the entity object with the new information
entityManager.refresh(entity);
return entity;
} else {
return entityManager.merge(entity);
}
}
}
@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = CustomBaseRepository.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
我有一个带有一些默认列值的 MySQL table 和 RestController。 当我 POST 到 /orders 端点时,我发送一个 JSON 对象,我得到一个响应,其中包含我已发送的信息 + MySQL 条目的自动生成的 ID。
我该怎么做才能使请求 return 成为已保存在数据库中的完整条目,包括默认列值?我知道,我在响应中获得的 ID,我可以用它来发出 GET 请求以检索所有数据,但我不想发出新请求。
MySQL 订单 table
`ID` int NOT NULL AUTO_INCREMENT,
`order_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`delivery_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
订单模型
@Entity
@Table(name="orders")
@Getter @Setter @DynamicUpdate @DynamicInsert
public class OrderModel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ID")
private Integer id;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="order_date")
Date orderDate;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="delivery_date")
Date deliveryDate;
protected OrderModel() {}
}
Spring RestController
@RestController
@AllArgsConstructor
@RequestMapping("orders")
public class OrdersController {
private final OrdersRepository ordersRepo;
@ResponseBody
@PostMapping
public OrderModel addOrder(@RequestBody OrderModel order) {
return ordersRepo.saveAndFlush(order);
}
}
POST 请求正文:
{}
POST 响应正文:
{
"id":40,
"orderDate":null,
"deliveryDate":null
}
一个可能的解决方案是仅在您需要的地方使用 EntityManager 的 refresh(Object entity) 方法对您要保存在数据库中的实体并获取它回来了。
另一种解决方案是在 存储库基础 class 中使用相同的 refresh(Object entity) 方法来实现全局且不更改任何其他内容,如下所示:
- 创建一个新的自定义 存储库基础 class 以覆盖 save 方法。 (包括刷新(对象实体))
- 让 spring-boot 知道您希望它使用您刚刚创建的自定义存储库基础 class。
- 现在,当您调用存储库的 save() 方法时,它将使用您在存储库基础中创建的方法 class。
public class CustomBaseRepository<T, ID> extends SimpleJpaRepository<T, ID> {
private final EntityManager entityManager;
private final JpaEntityInformation<T, ?> entityInformation;
CustomBaseRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
this.entityInformation = entityInformation;
}
@Transactional
@Override
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
entityManager.persist(entity);
//the next line of code saves the entry in the database for real and updates the entity object with the new information
entityManager.refresh(entity);
return entity;
} else {
return entityManager.merge(entity);
}
}
}
@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = CustomBaseRepository.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}