1

I have the following model:

enter image description here

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!

AlejoDev
  • 4,345
  • 9
  • 36
  • 67

3 Answers3

0

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();
AlejoDev
  • 4,345
  • 9
  • 36
  • 67
0

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;  
Angad Bansode
  • 825
  • 6
  • 15
-1

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);
Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • Thank you very much for your answer, but I would like to receive an explanation about it, for example, Why item1.setQuote(quote) if the item don't have a Quote – AlejoDev Aug 09 '18 at 21:09
  • 1
    Item is the holder of foreign key (contains PK of quote) so you must set relation on item. Right now you are doing other way around. As you are not doing that, hibernate generates insert SQL that does not contains pointer to quote - thus constraint violation. – Antoniossss Aug 09 '18 at 21:09
  • I am just to lazy to correct your model, so lets wait for someone else to do that for you. You can try yourself by starting with `private Quote quote;` – Antoniossss Aug 09 '18 at 21:14
  • @ Antoniossss Ok, For what reason? – AlejoDev Aug 09 '18 at 21:14
  • For the reason that normal model would have Item->private Quote quote; Thats the whole purpose and ideak behind **Object Relational Mapping** – Antoniossss Aug 09 '18 at 21:15
  • @ Antoniossss My database model is wrong or my mapping is wrong? – AlejoDev Aug 09 '18 at 21:27
  • @ Antoniossss Forgive me, but I do not understand why you say that my mapping is wrong, see the official documentation of Hibernate : http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#associations-one-to-many-unidirectional – AlejoDev Aug 09 '18 at 23:25
  • It is you that have to read it not me http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#associations-one-to-many-bidirectional – Antoniossss Aug 10 '18 at 05:21