【发布时间】:2017-08-12 18:16:44
【问题描述】:
我有两种处理实体的方法(在 Spring Boot 应用程序中)。该实体有两个字段,布尔值isDefault 和isPdfGenerated。第一个方法(从控制器调用)在创建新实体时更改 isDefault 标志,而第二个方法(从 @Scheduled 注释方法调用)在为该实体生成 pdf 文件后更改 isPdfGenrated .
我的问题是,有时第二种方法会找到 isPdfGenerated 标志设置为 false 的实体,即使文件已生成并保存在数据库中。
这两种方法都具有@Transactional 注释,并且实体的存储库接口扩展了JpARepository。
我的猜测是,第一种方法在第二种方法之前从数据库加载实体,但在第二种方法完成其工作后保存实体,从而覆盖 isPdfGenerated 标志。
这可能吗?如果答案是肯定的,应该如何处理这种情况? JPARepository 不应该处理从外部源更新实体的情况吗?
下面是一些代码来更好地说明这种情况。
我的控制器:
@Controller
@RequestMapping("/customers")
public class MyController {
@Autowired
private EntityService entityService;
@RequestMapping(value = "/{id}/changeDefault", method = RequestMethod.POST)
public String changeDefault(@PathVariable("id") Long customerId, @ModelAttribute EntityForm entityForm, Model model) {
Entity newDefaultEntity = entityService.updateDefaultEntity(customerId, entityForm);
if (newDefaultEntity == null)
return "redirect:/customers/" + customerId;
return "redirect:/customers/" + customerId + "/entity/default;
}
}
实体服务:
import org.springframework.transaction.annotation.Transactional;
@Service
public class EntityService {
@Autowired
private EntityRepository entityRepository;
@Autowired
private CustomerRepository customerRepository;
@Transactional
public Entity updateDefaultEntity(Long customerId, submittedData) {
Customer customer = customerRepository.findById(customerId);
if(customer == null)
return customer; // I know there are better ways to do this
Entity currentDefaultEntity = entityRepository.findUniqueByCustomerAndDefaultFlag(customer, true);
if(currentDefaultEntity == null)
return null; // I know there are better ways to do this also
Entity newDefaultEntity = new Entity();
newDefaultEntity.setField1(submittedData.getField1());
newDefaultEntity.setField2(submittedData.getField2());
newDefaultEntity.setCustomer(customer);
oldDefaultEntity.setDefaultFlag(false);
newDefaultEntity.setDefaultFlag(true);
entityRepository.save(newDefaultEntity);
}
@Transactional
public void generatePdfDocument(Entity entity) {
Document pdfDocument = generateDocument(entity);
if(pdfDocument == null)
return;
documentRepository.save(pdfDocument);
entity.setPdfGeneratedFlag(true);
entityRepository.save(entity);
}
}
计划任务:
@Component
public class ScheduledTasks {
private static final int SECOND_IN_MILLISECONDS = 1000;
private static final int MINUTE_IN_SECONDS = 60;
@Autowired
private EntityRepository entityRepository;
@Autowired
private DocumentService documentService;
@Scheduled(fixedDelay = 20 * SECOND_IN_MILLISECONDS)
@Transactional
public void generateDocuments() {
List<Quotation> quotationList = entityRepository.findByPdfGeneratedFlag(false);
for(Entity entity : entitiesList) {
documentService.generatePdfDocument(entity);
}
}
}
文档服务:
@Service
public class DocumentService {
@Autowired
private EntityRepository entityRepository;
@Autowired
private DocumentRepository documentRepository;
@Transactional
public void generatePdfDocument(Entity entity) {
Document pdfDocument = generateDocument(entity);
if(pdfDocument == null)
return;
documentRepository.save(pdfDocument);
entity.setPdfGeneratedFlag(true);
entityRepository.save(entity);
}
}
实体存储库:
@Repository
public interface EntityRepository extends JpaRepository<Entity, Long> {
Entity findById(@Param("id") Long id);
List<Entity> findByPdfGeneratedFlag(@Param("is_pdf_generated") Boolean pdfGeneratedFlag);
Entity findUniqueByCustomerAndDefaultFlag(
@Param("customer") Customer customer,
@Param("defaultFlag") Boolean defaultFlag
);
}
文档库:
@Repository
public interface DocumentRepository extends JpaRepository<Document, Long> {
Document findById(@Param("id") Long id);
}
实体:
@Entity
@Table(name = "entities")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "id")
public class Entity {
private Long id;
private boolean defaultFlag;
private boolean pdfGeneratedFlag;
private String field1;
private String field2;
private Customer customer;
public Entity() { }
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "is_default")
public boolean isDefaultFlag() {
return defaultFlag;
}
public void setDefaultFlag(boolean defaultFlag) {
this.defaultFlag = defaultFlag;
}
@Column(name = "is_pdf_generated")
public boolean isPdfGeneratedFlag() {
return pdfGeneratedFlag;
}
public void setPdfGeneratedFlag(boolean pdfGeneratedFlag) {
this.pdfGeneratedFlag = pdfGeneratedFlag;
}
@Column(name = "field_1")
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
@Column(name = "field_2")
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
@ManyToOne
@JoinColumn(name = "customer_id", referencedColumnName = "id", nullable = false)
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Entity quotation = (Entity) o;
return id != null ? id.equals(entity.id) : entity.id == null;
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
@Override
public String toString() {
return "Entity{" +
"id=" + id +
", pdfGeneratedFlag=" + pdfGeneratedFlag +
", defaultFlag=" + defaultFlag +
", field1=" + field1 +
", field2=" + field2 +
", customer=" + (customer == null ? null : customer.getId()) +
"}";
}
}
我省略了其他类,因为它们要么是 POJO (EntityForm),要么与其他领域模型类 (Document) 相同。
【问题讨论】:
-
您可以添加代码以及您正在做什么吗?
-
我已经用代码更新了问题。
标签: spring spring-mvc spring-boot spring-data-jpa spring-transactions