0

I have problem with JPA provided by Hibernate. Here are my entities:

@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); }
}

Here is my controller code:

@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);
        this.service.saveAction(action);
        sessionStatus.setComplete();
        return "redirect:/user/{username}";
    }
}

When method postAddAction is executed I got the following error:

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

in line where method saveAction is executed.

My code is modeled on this code https://github.com/spring-projects/spring-petclinic/blob/master/src/main/java/org/springframework/samples/petclinic/web/PetController.java#L79 but I don't know why I have this error because my code is pretty similar to this.

Can anybody help?

@Edit

I'm using spring Jpa repositories and code in service layer is very simple.

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

@Transactional
public void saveAction(Action action) {
    this.actionRepository.save(action);
}
1
  • Please share your Dao class and if possible table ddl Commented Jun 25, 2015 at 14:27

2 Answers 2

1

This problem arises when you dont include cascade="all" (if using xml) or cascade=CascadeType.ALL (if using annotations) on your collection mapping.

Which in your case exists but at the user entity but not at the action entity

hence we need to see how are we saving the action entity on the basis of which we can decide if we need to add cascade on action entity or not

Sign up to request clarification or add additional context in comments.

3 Comments

I just added my service layer to post
cant be of help without the dao method
I'm using spring repositories which is defined as interface.
0

Your EntityManager is not aware of the User instance that is injected in your method. Then, when you try to save the Action instance with a reference to unaware User instace you get the transient object exception.

I don't know exactly how your User instance is injected but with that instance you should use entity manager to find it from the database. Doing this, your entity manager is aware of which user you are trying to use. Take a look to this post

3 Comments

User instance comes from contextRegistration and It's being saved as session attribute. When spring call to postAddAction method It is injected to method from session. Here it was described stackoverflow.com/questions/3423262/…
Good. But Jpa does not know that object, is not in jps session. Try to look up the user with the entity manager and add that instance to your action

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.