简体   繁体   中英

Hibernate Persist Unidirectional One To Many Relationship

I have the following model:

在此处输入图片说明

The corresponding mapping is as follows:

Quote entity

@Entity
@Table(name="Quote")
@Getter
@Setter
public class Quote {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native", strategy = "native")
    @Column(name="idQuote")
    private int id;

    @Column(name="number")
    private String number;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name="Quote_idQuote")
    private Set<Item> item;
}

Item Entity

@Entity
@Table(name="Item")
@Getter
@Setter
public class Item {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native", strategy = "native")
    @Column(name="idItem")
    private int id;

    @Column(name="name")
    private String name;

    @Column(name="Quote_idQuote")
    private int quoteId;
}

The problem I have is that I can not persist a Quote with a list of Items, this is the code where I try to do it:

SessionFactory sessionFactory;
Configuration configuration= new Configuration();
configuration.configure();
sessionFactory=configuration.buildSessionFactory();
Session session= sessionFactory.openSession();
session.beginTransaction();

Quote quote= new Quote();
quote.setNumber("ASR3E4E");

Set<Item> items= new HashSet<Item>();

Item item1= new Item();
item1.setName("Item 1");

Item item2= new Item();
item1.setName("Item 2");

items.add(item1);
items.add(item2);        

quote.setItem(items);

session.persist(quote);

session.getTransaction().commit();

I get the following error:

Hibernate: insert into Quote (number) values (?)
Hibernate: insert into Item (name, Quote_idQuote) values (?, ?)
Aug 09, 2018 3:27:25 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1452, SQLState: 23000
Aug 09, 2018 3:27:25 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Cannot add or update a child row: a foreign key constraint fails (`test`.`item`, CONSTRAINT `fk_Item_Quote` FOREIGN KEY (`Quote_idQuote`) REFERENCES `quote` (`idquote`))
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:831)

Given the above, it makes me think... How to do so that automatically hibernate can persist the Quote with its Items. Why doesn't hibernate first generate the id of the Quote, persist it, and then, persists a Items? How should I do the mapping to maintain a unidirectional relationship and that I can do what I'm trying without problems?

Many Thanks!

The correct way to map the database model shown in the question is as follows:

Quote entity

@Entity
@Table(name="Quote")
@Getter
@Setter
public class Quote {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native", strategy = "native")
    @Column(name="idQuote")
    private int id;

    @Column(name="number")
    private String number;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "Quote_idQuote", nullable=false)
    private Set<Item> item;
}

Item entity

@Entity
@Table(name="Item")
@Getter
@Setter
public class Item {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native", strategy = "native")
    @Column(name="idItem")
    private int id;

    @Column(name="name")
    private String name;

}

And the code to persist Quote entity with Items:

SessionFactory sessionFactory;
Configuration configuration= new Configuration();
configuration.configure();
sessionFactory=configuration.buildSessionFactory();
Session session= sessionFactory.openSession();
session.beginTransaction();

Quote quote= new Quote();
quote.setNumber("ASR3E4E");

Set<Item> items= new HashSet<Item>();

Item item1= new Item();
item1.setName("Item 1");

Item item2= new Item();
item2.setName("Item 2");

items.add(item1);
items.add(item2);        

quote.setItem(items);

session.persist(quote);

session.getTransaction().commit();

Hibernate provide both side mapping for a flexible code. If you want to do any operation from valued entity(item). Do correct mapping

1) Quote.java class

    @OneToMany(cascade = CascadeType.ALL, mappedBy="quote",fetch=FetchType.Eager)

private Set<Item> item;

2) Inside Item.java class

    @ManyToOne
    @JoinColumn(name="Quote_idQuote") 
    private Quote quote;  

Try

   item1.setQuote(quote);
   item2.setQuote(quote);
   session.persist(quote);

In your case it is impossible to succed as you cannot set relations here: It would work (and still be very bad) if:

remove cascade = CascadeType.ALL,

session.persist(quote); // this must be done first to actually get bloody quote ID that you can propagate
item1.setQuoteId(quote.getId()); //or something to set quoteid
item2.setQuoteId(quote.getId())=quote.id; //or something to set quoteid
session.persist(item1);
session.persist(item2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM