Spring, доступ к методу с другого контроллера - PullRequest
0 голосов
/ 16 января 2019

Я получил объект B, связанный с помощью ManyToOne с другим объектом A. При записи метода add в его контроллере я, очевидно, передаю поле Экземпляра A в качестве параметра, из которого я выбираю весь объект, чтобы извлечь его ID, который я использовать в качестве ключа для отношений. Если экземпляр A, который я пытаюсь выбрать, не существует, я хочу, чтобы он был создан (поле, которое я передаю в качестве параметра, достаточно для его конструктора). Могу ли я сделать это без создания экземпляра контроллера A внутри контроллера B? Кажется странным ...

UPDATE Я переписал большую часть своего проекта, благодаря подсказкам @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 голосов
/ 16 января 2019

Если я вас правильно понимаю:

  1. Вам не нужен контроллер A внутри B. Контроллеры не несут ответственности за сохранение сущностей, они предназначены только для веб-обмена. Например, вы можете внедрить свой компонент @Repository или @Service объекта A в контроллер B и вызвать метод save () для своих объектов. (на мой взгляд, лучшим подходом будет внедрение AResporitory внутри класса BService)

    ОБНОВЛЕНО

    Пример:

    @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 (например, пользователь выбрал его в форме пользовательского интерфейса).

  2. Другим подходом будет использование каскадных вставок в вашем праве B.

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

ОБНОВЛЕНО Каскады не создают новые строки уже существующих, но Hibernate проверяет существование строки только по первичному ключу. Если у вашего объекта сущности есть пустой первичный ключ, это означает, что это новый объект, и вам нужно вставить новую строку. Во многих случаях контроллер получит заполненное поле Id marca, потому что, как я писал ранее, пользователь может выбрать его в форме пользовательского интерфейса, используя, например, своего рода «компонент выбора». Но если в вашем случае пользователь не может выбрать марку и может только ввести его имя, то, конечно, каскады не будут хорошим решением, и вы сможете сначала искать марку по номеру (как вы делаете в своем коде) .

...