Unidirectional ManyToOne: Why transient instance saved with CascadeType.ALL but not CascadeType.PERSIST

StackOverflow https://stackoverflow.com/questions/23521039

質問

I am getting org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: safu.Publisher exception when I try to run the following code:

public class SafuClient {
    public static void main(String[] args) {

        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();

            Publisher publisher = new Publisher("ABC", "ABC Co.");
            Book book = new Book("1-932394-88-5", "Safu", publisher);

            session.save(book);        

            session.getTransaction().commit();

    }
}

I have a Many-to-One relationship from Book to Publisher. Book and Publisher entities follows:


@Entity
public class Book {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)   
    private Long id;
    private String isbn;
    private String name;

    @ManyToOne(cascade={CascadeType.PERSIST})
    @JoinColumn(name="publisher_id")
    private Publisher publisher;    

    public Book() {}
    public Book(String isbn, String name, Publisher publisher) {
        this.isbn = isbn;
        this.name = name;
        this.publisher = publisher;
    }

}

@Entity
public class Publisher {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String code;
    private String name;

    public Publisher() {}
    public Publisher(String code, String name) {
        this.code = code;
        this.name = name;
    }

}

If I replace @ManyToOne(cascade={CascadeType.PERSIST}) with @ManyToOne(cascade={CascadeType.ALL}) in the Book entity everything works just fine.

Could somebody explain why is it happening?

役に立ちましたか?

解決

Try session.persist(book); this solves the problem instead of session.save(book);

他のヒント

The session.save(book) method works by removing the cascade attribute (cascade={CascadeType.PERSIST}) from @ManyToOne annotation in the Book entity and adding the @Cascade (value=CascadeType.SAVE_UPDATE) on the publisher field instead.

The @Cascade (value=CascadeType.SAVE_UPDATE) uses Hibernate's native annotations.


Follows the updated Book.java that worked:


@Entity
public class Book {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)   
    private Long id;
    private String isbn;
    private String name;

    @ManyToOne
    @JoinColumn(name="publisher_id")
    @Cascade(value=CascadeType.SAVE_UPDATE)
    private Publisher publisher;    

    public Book() {}
    public Book(String isbn, String name) {
        this.isbn = isbn;
        this.name = name;
    }   
    public Book(String isbn, String name, Publisher publisher) {
        this.isbn = isbn;
        this.name = name;
        this.publisher = publisher;
    }   
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top