I am trying to create a mapping in Hibernate on an Entity with ManyToOne relationship. I am trying this:
CampaignItemSlot class:
package models;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "campaign_item_slots")
public class CampaignItemSlot {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
#JoinColumn(name = "advert_slot_id")
#ManyToOne
private AdvertSlot advertSlot;
private boolean active;
private Timestamp date_created;
private Timestamp date_updated;
public CampaignItemSlot() {
super();
// TODO Auto-generated constructor stub
}
}
However I get this in the log file:
Caused by: org.hibernate.HibernateException: Missing column: advertSlot_id in text_advertising.campaign_item_slots
This is my table SQL:
CREATE TABLE IF NOT EXISTS `text_advertising`.`campaign_item_slots` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`campaign_item_id` BIGINT NOT NULL,
`advert_slot_id` BIGINT NOT NULL,
`active` TINYINT(1) NOT NULL DEFAULT TRUE,
`date_created` DATETIME NOT NULL,
`date_updated` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `fk_campaignitems_1_idx` (`campaign_item_id` ASC),
INDEX `fk_campaignitems_2_idx` (`advert_slot_id` ASC),
CONSTRAINT `fk_campaign_item_slots_1`
FOREIGN KEY (`campaign_item_id`)
REFERENCES `text_advertising`.`campaignitems` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_campaign_item_slots_2`
FOREIGN KEY (`advert_slot_id`)
REFERENCES `text_advertising`.`advert_slots` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
AdvertSlot class:
package models;
import java.sql.Timestamp;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "advert_slots")
public class AdvertSlot {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
#ManyToOne
private Publication publication;
private String name;
private String description;
private boolean active;
private Timestamp date_created;
private Timestamp date_updated;
public AdvertSlot() {
super();
// TODO Auto-generated constructor stub
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Publication getPublication() {
return publication;
}
public void setPublication(Publication publication) {
this.publication = publication;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Timestamp getDate_created() {
return date_created;
}
public void setDate_created(Timestamp date_created) {
this.date_created = date_created;
}
public Timestamp getDate_updated() {
return date_updated;
}
public void setDate_updated(Timestamp date_updated) {
this.date_updated = date_updated;
}
}
Somehow Hibernate is not seeing my advert_slot_id, help please?
The answer here is to create a custom naming strategy by extending org.hibernate.cfg.DefaultNamingStrategy and then referencing it via hibernate config: hibernate.ejb.naming_strategy
Here is an example:
#Override
public String foreignKeyColumnName(String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName) {
String changed = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, propertyName) + "_id";
return changed;
}
It will work.Try this way:
First table:
#Table(name = "buyer_city")
public class BuyerCity{
//other fields
.....
#OneToMany(mappedBy="buyerCity", fetch = FetchType.LAZY)
#JsonManagedReference
private Set<BuyerCityMapping> buyerCityMapping = new HashSet<>();
}
Second table:
#Table(name = "buyer_city_mapping")
public class BuyerCityMapping{
//other fields
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JsonBackReference
#JoinColumn(name = "buyer_city_id")
private BuyerCity buyerCity;
}
Related
I'm having problems in mapping foreign keys as the primary key.
My tables are:
client:
PK: id_client
games:
PK: id_game
tickets:
PK: (id_game_fk references game(id_game), id_client_fk references client(id_client))
And here are the classes I have defined as entities:
Client.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "client")
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_client")
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Games.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "games")
public class Games {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_game")
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Ticket.java:
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import Client;
import Games;
#Entity
#Table(name = "tickets")
public class Ticket implements Serializable {
private static final long serialVersionUID = 3287868602749718327L;
#EmbeddedId
private TicketId ticketId;
#ManyToOne
#JoinColumn(name = "id_game")
private Games games;
#ManyToOne
#JoinColumn(name = "id_client")
private Client client;
public TicketId getId() {
return ticketId;
}
public void setId(TicketId id) {
this.ticketId = id;
}
public Games getGames() {
return games;
}
public void setGames(Games games) {
this.games = games;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
}
TicketId.java:
import java.io.Serializable;
import javax.persistence.Embeddable;
#Embeddable
public class TicketId implements Serializable {
private static final long serialVersionUID = 6220676431741410239L;
private int idGameFk;
private int idClientFk;
public TicketId(int idGameFk, int idClientFk) {
this.idGameFk = idGameFk;
this.idClientFk = idClientFk;
}
public int getIdGameFk() {
return idGameFk;
}
public void setIdGameFk(int idGameFk) {
this.idGameFk = idGameFk;
}
public int getIdClientFk() {
return idClientFk;
}
public void setIdClientFk(int idClientFk) {
this.idClientFk = idClientFk;
}
}
I have tried all the advices I have found so far, but none of them helped. Also, I need this PK to be composed by foreign keys, so I really need help to solve out, how should I map it correctly.
You can use #MapsId :
#Entity
#Table(name = "tickets")
public class Ticket implements Serializable {
private static final long serialVersionUID = 3287868602749718327L;
#EmbeddedId
private TicketId ticketId;
#ManyToOne
#MapsId("idGameFk")
#JoinColumn(name = "id_game_fk")
private Games games;
#ManyToOne
#MapsId("idClientFk")
#JoinColumn(name = "id_client_fk")
private Client client;
....
}
More info here : http://docs.oracle.com/javaee/6/api/javax/persistence/MapsId.html
I want to establish one to many relation between table vendor detail and product detail. like one vendor can have multiple products. but when i am inserting data into table its inserting all the four fields but not mapping vendorid into ProductDetail Table
and query generated is this.
Hibernate: insert into ProductInfo (productCategory, productDetails, productPrice, VendorId) values (?, ?, ?, ?) It shuld map vendor ID also but in table its empty.
VendorDetail.java
package com.cts.entity;
import javax.persistence.*;
#Entity
#Table(name = "VendorInfo")
public class VendorDetails {
#Id
#Column
private Long VendorId;
#OneToMany
private ProductDetails productdetail;
#Column
private String VendorName;
#Column
private String Password;
public String getVendorName() {
return VendorName;
}
public void setVendorName(String vendorName) {
VendorName = vendorName;
}
public Long getVendorId() {
return VendorId;
}
public void setVendorId(Long vendorId) {
VendorId = vendorId;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
}
ProductDetails.java
package com.cts.entity;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity#Table(name = "ProductInfo")
public class ProductDetails {
#ManyToOne(cascade = CascadeType.ALL)#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
public ProductDetails() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int productId;
#Column
private String productCategory;
#Column
private String productDetails;
#Column
private String productPrice;
public VendorDetails getVendordetails() {
return vendordetails;
}
public void setVendordetails(VendorDetails vendordetails) {
this.vendordetails = vendordetails;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getProductCategory() {
return productCategory;
}
public void setProductCategory(String productCategory) {
this.productCategory = productCategory;
}
public String getProductDetails() {
return productDetails;
}
public void setProductDetails(String productDetails) {
this.productDetails = productDetails;
}
public String getProductPrice() {
return productPrice;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
}
DAO class ProductDetailDaoImpl.java
package com.cts.Dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.cts.entity.ProductDetails;
import com.cts.entity.to.ProductDetailsTo;
#Repository
public class ProductDetailDaoImpl implements ProductDetailDao {
#Autowired
SessionFactory sessionFactory;
#Transactional
public boolean saveProductInfo(ProductDetailsTo productTo) {
System.out.println("M in Registration DAO");
System.out.println(productTo.getProductCategory());
System.out.println(productTo.getProductDetails());
System.out.println(productTo.getProductId());
System.out.println(productTo.getProductPrice());
//getting productTo data to entity class
ProductDetails prodet = productTo.getEntity();
System.out.println("Value of product details is:" + prodet.getProductDetails());
sessionFactory.getCurrentSession().save(prodet);
return false;
}
}
VendorDetails has many ProductDetails so you need to make one to many annotation like this:-
#OneToMany(mappedBy="vendordetails") //mappedBy value will be what you declared //in ProductDetails class.
private Collection<ProductDetails> productdetail=new ArrayList<ProductDetails>;
and create the setter and getter of this.
Now in ProductDetails class you need to annotate many to one like this:-
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
Then a new column named 'VendorId' will be create in table 'ProductInfo' and since declare mappedBy value="vendordetails" so each vendor id would be insert.
I think you should replace the code
#OneToMany
private ProductDetails productdetail;
to
#OneToMany
private Set productdetailSet;
And create setter and getter for this.
You can visit the blog http://gaurav1216.blogspot.in/2014/01/hibernate-tutorial-day-5.html for one to many using annotation.
These are my pojo class
Orderdetail.java
package online.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "orderdetail")
public class OrderDetail {
#Id
#Column(name="order_detail_id")
private int order_detail_id;
#Column(name="bill")
private float bill;
#ManyToOne
#JoinColumn(name = "p_id" )
private Product p_id;
#ManyToOne
#JoinColumn(name = "o_id" )
private Order o_id;
public int getOrder_detail_id() {
return order_detail_id;
}
public void setOrder_detail_id(int order_detail_id) {
this.order_detail_id = order_detail_id;
}
public float getBill() {
return bill;
}
public void setBill(float bill) {
this.bill = bill;
}
public Product getP_id() {
return p_id;
}
public void setP_id(Product p_id) {
this.p_id = p_id;
}
public Order getO_id() {
return o_id;
}
public void setO_id(Order o_id) {
this.o_id = o_id;
}
}
My Order.java
package online.model;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
#Entity
#Table(name = "ordertable")
public class Order {
#Id
#Column(name = "order_id")
private int order_id;
#OneToMany(mappedBy = "o_id",cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<OrderDetail> orderdetail;
#ManyToOne
#JoinColumn(name = "u_id")
private UserDetail u_id;
public UserDetail getU_id() {
return u_id;
}
public void setU_id(UserDetail u_id) {
this.u_id = u_id;
}
#Column(name = "date")
#Temporal(TemporalType.TIMESTAMP)
private Date date;
#Column(name = "totalbill")
private Float totalbill;
public Float getTotalbill() {
return totalbill;
}
public void setTotalbill(Float totalbill) {
this.totalbill = totalbill;
}
public List<OrderDetail> getOrderdetail() {
return orderdetail;
}
public void setOrderdetail(List<OrderDetail> orderdetail) {
this.orderdetail = orderdetail;
}
public int getOrder_id() {
return order_id;
}
public void setOrder_id(int order_id) {
this.order_id = order_id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
When ever I am trying to save order class I want my orderdetail class also get saved but when I am trying to save the List in order,Is is not getting saved and there is not error provided by hibernate that can help...
Thanks for the help
when i am trying to to persist the order class
Hibernate: select orderdetai_.order_detail_id, orderdetai_.bill as bill7_, orderdetai_.o_id as o3_7_, orderdetai_.p_id as p4_7_ from orderdetail orderdetai_ where orderdetai_.order_detail_id=?
This what I am getting output.
This is my code which save the class
#Override
public boolean payment(String username, Integer ordernumber, Date date,
Float totalbill, List<Integer> list) {
Session session = sessionFactory.openSession();
Transaction tranction = session.beginTransaction();
try {
Query query = session
.createQuery("from UserDetail where user_username = :username");
query.setParameter("username", username);
List<UserDetail> userdetaillist = query.list();
UserDetail userdetail = userdetaillist.get(0);
query = session
.createQuery("from ProductDetail where product_detail_id in(:list)");
query.setParameterList("list", list);
List<ProductDetail> productdetail = query.list();
Order order = new Order();
order.setOrder_id(ordernumber);
order.setDate(date);
order.setU_id(userdetail);
order.setTotalbill(totalbill);
List<OrderDetail> orderdetail = new ArrayList<OrderDetail>();
OrderDetail ordetail = new OrderDetail();
for (ProductDetail pro : productdetail) {
ordetail.setO_id(order);
ordetail.setP_id(pro.getProduct_id());
ordetail.setBill(pro.getProduct_id().getProduct_sell_price());
orderdetail.add(ordetail);
}
System.out.print("totalbill" + totalbill);
System.out.println(orderdetail);
order.setOrderdetail(orderdetail);
session.save(order);
tranction.commit();
return true;
} catch (Exception e) {
tranction.rollback();
e.getStackTrace();
}
return false;
}
I think ordetail has to be created inside the for.. You are modifying the same object for each productdetail. Should be like this:
List<OrderDetail> orderdetail = new ArrayList<OrderDetail>();
OrderDetail ordetail = null;
for (ProductDetail pro : productdetail) {
ordetail = new OrderDetail();
ordetail.setO_id(order);
ordetail.setP_id(pro.getProduct_id());
ordetail.setBill(pro.getProduct_id().getProduct_sell_price());
orderdetail.add(ordetail);
}
Hey I have recheck my pojo class and I found out the mistake I have done. I have made change and it work properly now.
I was not setting the the id for Orderdetail table. It was auto increment in database.
So it was giving me error ""
So I have made change in orderdetail iD
"#GeneratedValue(strategy=GenerationType.AUTO)" So now It is working fine cause now hibernate know that the id will get value from database.
Thanks for the help and for your time
My database has two table. One of University, another is Faculty. They are one to many relationship
package server.hibernate.domain;
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
#Entity
#Table(name = "UNIVERSITY")
public class University implements Serializable{
private Long _id;
private int _version;
private String _universityName;
private String _countryLocated;
private Set<Faculty> _faculties = new HashSet<Faculty>();
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID")
public Long getId() {
return _id;
}
public void setId(Long _id) {
this._id = _id;
}
#Version
#Column(name = "VERSION")
public int getVersion() {
return _version;
}
public void setVersion(int _version) {
this._version = _version;
}
#Column(name = "UNIVERSITY_NAME", nullable=false)
public String getUniversityName() {
return _universityName;
}
public void setUniversityName(String _universityName) {
this._universityName = _universityName;
}
#Column(name = "COUNTRY_LOCATED")
public String getCountryLocated() {
return _countryLocated;
}
public void setCountryLocated(String _countryLocated) {
this._countryLocated = _countryLocated;
}
#OneToMany(mappedBy="university", targetEntity=Faculty.class, orphanRemoval=true, fetch=FetchType.EAGER, cascade=CascadeType.ALL)
public Set<Faculty> getFaculties() {
return _faculties;
}
public void setFaculties(Set<Faculty> faculties) {
this._faculties = faculties;
}
public String toString(){
return new String("UniversityID:"+_id
+ " UniversityName:"+_universityName
+" CountryLocated:"+_countryLocated);
}
}
This is what I have set in University class.
package server.hibernate.domain;
import static javax.persistence.GenerationType.IDENTITY;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
#Entity
#Table(name="FACULTY")
public class Faculty implements Serializable{
private Long _id;
private int _version;
private String _facultyName;
private String _deanName;
private University _university;
private Set<Student> _students = new HashSet<Student>();
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID")
public Long getId() {
return _id;
}
public void setId(Long id) {
this._id = id;
}
#Version
#Column(name = "VERSION")
public int getVersion() {
return _version;
}
public void setVersion(int version) {
this._version = version;
}
#Column(name="FACULTY_NAME", nullable=false)
public String getFacultyName() {
return _facultyName;
}
public void setFacultyName(String facultyName) {
this._facultyName = facultyName;
}
#Column(name="DEAN_NAME")
public String getDeanName() {
return _deanName;
}
public void setDeanName(String dean_name) {
this._deanName = dean_name;
}
#ManyToOne
#JoinColumn(name = "UNIVERSITY_ID", nullable=false)
public University getUniversity() {
return _university;
}
public void setUniversity(University university) {
this._university = university;
}
#OneToMany(mappedBy="faculty", targetEntity=Student.class, orphanRemoval=true, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
public Set<Student> getStudents() {
return _students;
}
public void setStudents(Set<Student> students) {
this._students = students;
}
public String toString(){
return new String("FacultyID:"+_id
+" FacultyName:"+_facultyName
+" DeanName:"+_deanName);
}
}
This is my faculty class
But when I use sessionFactory.delete(university). I still have this exception
Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: could not delete: [server.hibernate.domain.University#1]; SQL [delete from UNIVERSITY where ID=? and VERSION=?]; constraint ["FKE9B72644368E5BBD: PUBLIC.FACULTY FOREIGN KEY(UNIVERSITY_ID) REFERENCES PUBLIC.UNIVERSITY(ID)"; SQL statement:
delete from UNIVERSITY where ID=? and VERSION=? [23503-160]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not delete: [server.hibernate.domain.University#1]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)
at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy19.removeUniversity(Unknown Source)
at main.TestHibernateMain.test(TestHibernateMain.java:73)
at main.TestHibernateMain.main(TestHibernateMain.java:22)
Caused by: org.hibernate.exception.ConstraintViolationException: could not delete: [server.hibernate.domain.University#1]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2710)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2893)
at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:97)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:189)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
... 9 more
Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FKE9B72644368E5BBD: PUBLIC.FACULTY FOREIGN KEY(UNIVERSITY_ID) REFERENCES PUBLIC.UNIVERSITY(ID)"; SQL statement:
delete from UNIVERSITY where ID=? and VERSION=? [23503-160]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
at org.h2.message.DbException.get(DbException.java:169)
at org.h2.message.DbException.get(DbException.java:146)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:398)
at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:415)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:291)
at org.h2.table.Table.fireConstraints(Table.java:861)
at org.h2.table.Table.fireAfterRow(Table.java:878)
at org.h2.command.dml.Delete.update(Delete.java:98)
at org.h2.command.CommandContainer.update(CommandContainer.java:73)
at org.h2.command.Command.executeUpdate(Command.java:219)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:143)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2692)
... 20 more
Can anyone suggest a solution?
Thanks!
I solved my problem by myself.
It is a fetch problem.
When I try remove University by using sessionFactory.delete(university), this university does not fetch any faculties. So the removal will not be cascade enabled.
This because you are trying to delete the UNIVERSITY which is associated with other faculties
thus you have to first delete associated faculties before deleting the university.
I have the following problem.
Here are my entities.
TestTeam.java
package utils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "TEST_TEAM")
public final class TestTeam implements Serializable {
/**
*
*/
private static final long serialVersionUID = -7275223441128447981L;
#Id
#Column(name = "NAME")
private String name;
#OneToMany(mappedBy = "playerId", cascade = CascadeType.ALL)
private List<TestPlayer> test1List;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<TestPlayer> getTest1List() {
return test1List;
}
public void setTest1List(List<TestPlayer> test1List) {
this.test1List = test1List;
}
public TestTeam() {
}
public TestTeam(final String name, final List<TestPlayer> test1List) {
this.name = name;
this.test1List = new ArrayList<>(test1List);
}
}
TestPlayer.java
package utils;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "TEST_PLAYER")
public class TestPlayer implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2792602076488917813L;
#Id
private long playerId;
#Column(name = "NAME", nullable = false)
private String playerName;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "TEAM_NAME")
private TestTeam team;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "PREVIOUS_TEST_TEAM")
private Map<Integer, TestTeam> previousTests = Collections.emptyMap();
public TestPlayer() {
// TODO Auto-generated constructor stub
}
public TestPlayer(final long playerId) {
this.playerId = playerId;
}
public String getName() {
return playerName;
}
public void setName(String name) {
this.playerName = name;
}
/**
* #return the team
*/
public TestTeam getTeam() {
return team;
}
/**
* #param team the team to set
*/
public void setTeam(TestTeam team) {
this.team = team;
}
public Map<Integer, TestTeam> getPreviousTests() {
return previousTests;
}
public void setPreviousTests(Map<Integer, TestTeam> previousTests) {
this.previousTests = previousTests;
}
public TestPlayer(final String name,
final Map<Integer, TestTeam> previousTests) {
this.playerName = name;
this.previousTests = new HashMap<>(previousTests);
}
}
The following annotated collection.
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "PREVIOUS_TEST_TEAM")
private Map<Integer, TestTeam> previousTests = Collections.emptyMap();
produces by default a unique constraint for the foreign key from TestTeam entity.
create table PLAYERS_PREVIOUS_TEAMS (
Player_ID bigint not null,
previousTeamMap_NAME varchar(255) not null,
previousTeamMap_KEY integer,
primary key (Player_ID, previousTeamMap_KEY)
)
alter table PLAYERS_PREVIOUS_TEAMS
add constraint UK_f7nfahws0ttuhe5p7lpxt3vfv unique (previousTeamMap_NAME)
I do not need this constraint and I would like to switch off this behaviour so that Hibernate does not generate it. I have spent some time looking on the internet but I did not find anything. I do not want to introduce #OneToMany and many #ManyToOne by introducing another entity. Did anyone face a similar problem in the past?
I worked around my issue by changing #ElementCollection to #ManyToMany annotation.
#ManyToMany(fetch = FetchType.EAGER)
#CollectionTable(name = "PREVIOUS_TEST_TEAM")
private Map<Integer, TestTeam> previousTests = Collections.emptyMap();