Spring,从其他控制器访问方法

时间:2019-01-15 23:46:58

标签: spring hibernate controller spring-data-jpa

我得到了一个由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);
}

1 个答案:

答案 0 :(得分:0)

如果我正确理解您的话:

  1. 您在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表单上选择了它)。

  2. 另一种方法是在您的B实体中使用cascade inserts

    @Entity
    public class EntityB {
    
        @ManyToOne(cascade = CascadeType.PERSIST)
        protected EntityA entityA;
    
    }
    

已更新 Cascades不会创建已经存在的新行,但是Hibernate仅通过主键检查行的存在。如果您的实体对象的主键为空,则表示它是一个新对象,您需要插入新行。在许多情况下,控制器将接收到一个已填充的marca的ID字段,因为正如我之前所写的,您可以使用某种“选择组件”在UI表单上选择它。但是,如果在您的情况下,用户无法选择marca,而只能输入其名称,那么,当然,级联将不是一个好的解决方案,您可以首先通过nome搜索marca(就像在代码中所做的那样)