我得到了一个由ManyToOne与另一个实体A绑定的实体B。在其控制器中编写add方法,我显然将A实例的字段作为参数传递,从中选择整个对象以提取其ID,用作关系的关键。 如果我尝试选择的A实例不存在,则希望创建它(作为参数传递的字段足以构成其构造函数)。 我可以在不实例化控制器B内部的控制器A的情况下做到这一点吗?似乎很奇怪...
更新 由于@Artur Vakhrameev的提示
,我重写了项目的大部分内容我为每个实体创建了一个服务,并在另一个内部实例化了其中的一个。这是“许多方面”关系实体的服务
@Transactional
@Service
public class LineaService {
@Autowired
private LineaRepository lineaRepo;
@Autowired
private MarcaService marcaService;
public Linea create(Linea linea) {
Linea nuovaLinea = new Linea();
nuovaLinea.setNome(linea.getNome());
if (marcaService.findByName(linea.getMarca().getNome()) == null)
nuovaLinea.setMarca(marcaService.create(linea.getMarca()));
else
nuovaLinea.setMarca(linea.getMarca());
lineaRepo.save(nuovaLinea);
nuovaLinea.getMarca().addLinea(nuovaLinea);
return nuovaLinea;
}
现在这是我控制器中的简单add
后映射,除去了所有业务逻辑
@PostMapping("/add")
public String aggiungiLinea(Linea linea) {
lineaService.create(linea);
return "redirect:list";
}
更新2(该更新似乎可以正常工作)
public Linea create(Linea linea) {
Marca marcaAssociata = marcaService.findByName(linea.getMarca().getNome());
if (marcaAssociata == null)
linea.setMarca(marcaService.create(linea.getMarca()));
else
linea.setMarca(marcaAssociata);
return lineaRepo.save(linea);
}
答案 0 :(得分:0)
如果我正确理解您的话:
您在B内不需要控制器A。控制器没有保存实体的责任,它们仅与Web交换有关。例如,您可以将A实体的@Repository或@Service组件注入B控制器,然后为您的实体调用save()方法。 (我认为更好的方法是在BService类中注入AResporitory)
已更新
示例:
@Transactional
@Service
public class LineaService {
@Autowired
private LineaRepository lineaRepo;
@Autowired
private MarcaService marcaService;
public Linea create(Linea linea) {
//creates new marca if not exists
//no need for this block if you add cascade insert to your entity
if (linea.getMarca().getId() == null) {
marcaService.create(linea.getMarca());
}
return lineaRepo.save(linea);
}
如果您设置了现有的marca值,那么您会在之前找到它,因此在这种情况下,Id
将具有一些值(例如,用户在UI表单上选择了它)。
另一种方法是在您的B实体中使用cascade inserts。
@Entity
public class EntityB {
@ManyToOne(cascade = CascadeType.PERSIST)
protected EntityA entityA;
}
已更新 Cascades不会创建已经存在的新行,但是Hibernate仅通过主键检查行的存在。如果您的实体对象的主键为空,则表示它是一个新对象,您需要插入新行。在许多情况下,控制器将接收到一个已填充的marca的ID字段,因为正如我之前所写的,您可以使用某种“选择组件”在UI表单上选择它。但是,如果在您的情况下,用户无法选择marca,而只能输入其名称,那么,当然,级联将不是一个好的解决方案,您可以首先通过nome搜索marca(就像在代码中所做的那样)