Unsaved transient entity instance

0

Witajcie,
Znalazłem bardzo fajny projekt na githubie i postanowiłem napisać coś na jego podstawie. Padło na prostą aplikacje gdzie można dodawać użytkowników, a do każdego użytkownika jakąś akcję. Problem w tym, że podczas pisania kodu trafiłem na błąd. Treść tego błędu jest dla mnie całkowicie zrozumiała, tak samo jak zasada działania kodu w poniższym projekcie. Problem w tym że nie mam pomysłu jak zaradzić temu błędowi i dziwię się czemu nie występuje on w wymienionym projekcie, ponieważ mój kod jest prawie identyczny.
https://github.com/spring-projects/spring-petclinic

Moje encje:

@Entity
public class Action {
    @Id
    @GeneratedValue
    private Integer id;

    @Column
    private String name;

    @JoinColumn
    @ManyToOne
    private User user;

    public Integer getId() { return this.id; }
    protected void setId(Integer id) { this.id = id; }

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    public void getUser() { return this.user; }
    protected void setUser(User user) { this.user = user; }
}
@Entity
public class User {
    @Id
    @GeneratedValue
    private Integer id;

    @Column
    private String name;

    @OneTomany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<Action> actions = new ArrayList<>();

    public Integer getId() { return this.id; }
    protected void setId(Integer id) { this.id = id; }

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    public void addAction(Action action) {
        action.setUser(this);
        actions.add(action);
    }
    public void removeAction(Action action) {
        actions.remove(action);
        action.setUser(null);
    }
    public List<Action> getActions() { return Collections.unmodifiableList(actions); }
}

Warstwa serwisowa:

@Transactional(readyOnly = true)
public User getByName(String name) {
    return this.userRepository.getByName(name);
}

@Transactional
public void saveAction(Action action) {
    this.actionRepository.save(action);
}

I warstwa controller:

@Controller
@RequestMapping("/user/{username}")
@SessionAttributes("user")
public class ActionController {
    @Autowired
    private TestService service;

    @ModelAttribute("user")
    public User contextRegistration(@PathVariable("username") String username) {
        return this.service.getByName(username);
    }

    @RequestMapping("")
    public String userView() {
        return "user";
    }

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String addAction(@ModelAttribute Action action) {
        return "addAction";
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String postAddAction(@Valid Action action, BindingResult result, User user, SessionStatus sessionStatus) {
        if(result.hasErrors()) {
            return "addAction";
        }

        user.addAction(action);
        // W poniższej linijce zostaje wyrzucony wyjątek
        this.service.saveAction(action);
        sessionStatus.setComplete();
        return "redirect:/user/{username}";
    }
}

Tutaj link do podobnej linijki w tym projekcie: https://github.com/spring-projects/spring-petclinic/blob/master/src/main/java/org/springframework/samples/petclinic/web/PetController.java#L99

No i mój bład:

org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : pl.zaprogramowany.test.model.Action.user -> pl.zaprogramowany.test.model.User

Macie jakiś pomysł jak temu zaradzić? Wiecie co robię źlę?

0

To co mi sie nasuwa: nie zapisujesz usera po dodaniu akcji. Rozumiem ze akcja ma juz ustawionego usera w momencie zaladowania tej metody z parametru user tak ? w ogole nie wiem po co jest service.saveAction skoro mozesz zapisac usera kaskadowo z nowymi akcjami (updateowac) - taki strzal // pisane z komorki
// dodalem posta zeby nie dostac opierdzielu od moderatora

0

Problem w tym że w kontrolerze nie mam aktywnej trasakcji, która mogła by zostać zacommitowana. Dlatego też metoda addAction doda akcje do Encji User, ale nie zostanie wykonane zapytanie.

0

Pozwole sobie odswierzyc temat bo mam ten sam problem problem co kolega.. i nie umiem z nim sobie poradzic.
To co chce uzyskac to przy podaniu takiego zapytania :
Projekt:

{
 "name": "Testnowy",
 "owner_id": 1
 }

Zeby stworzyl sie obiet Projekt z FK owner_id. Jezeli nie istnieje user o takim owner_id to ma rzucic wyjatkiem.

Na chwile obecna mam to co kolega wyzej... ( w zaleznosci od ustawien.. zdarza mi sie tez miec blad no-constuctor int... )
Jezeli podam w tym jsonie pelnego usera, to wtedy user tez tworzy sie w bazie i to jest zdecydowanie to zachowanie ktorego nie chce.

1 użytkowników online, w tym zalogowanych: 0, gości: 1