I'm new to hibernate, after following some tutorials, i tried to make my self example of storing persisting data with hibernate. Using: MySQL 5.7 and Hibernate 5.0.3 with Eclipse IDE.
I looked for similar topics but no solution running.
My Java Classes are:
Dossier.java (Folder containing multiple files)
package com.testhibernate;
import java.util.ArrayList;
import java.util.List;
public class Dossier {
private Long id;
private String name;
private List<Fichier> files;
public Dossier()
{
setName("Folder");
files = new ArrayList<Fichier>();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Fichier> getFiles()
{
return files;
}
public void addFile(Fichier a_file)
{
a_file.setFolder(this);
files.add(a_file);
}
}
Fichier.java (File contained in a Folder) package com.testhibernate;
public class Fichier {
private Long id;
private String name;
private Dossier folder;
public Fichier()
{
setName("Fichier");
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setFolder(Dossier a_folder) {
folder = a_folder;
}
public Dossier getFolder() {
return (folder);
}
}
I also created a class to handle save requests
ManageDB.java (Contains starting main function)
package com.testhibernate.dbaccess;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import com.testhibernate.Dossier;
import com.testhibernate.Fichier;
public class ManageDB {
private static SessionFactory factory;
private static boolean configured = false;
private static void log(String a_str)
{
System.out.println("[[MANAGEDB@: " + a_str + "]");
}
/**
* @name setup
* @brief configure the factory session
*/
public static void setup()
{
log("Setup");
ServiceRegistry serviceRegistry;
if (!configured)
{
try{
Configuration configuration = new Configuration();
configuration.configure();
configuration.addClass(Dossier.class);
configuration.addClass(Fichier.class);
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
factory = configuration.buildSessionFactory(serviceRegistry);
configured = true;
}catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
}
}
/**
* @name addFolder.
* @param a_folder the folder to save
* @return ID of the added call.
*/
public static Long addFolder(Dossier a_folder)
{
log("addFolder");
Session session = factory.openSession();
Transaction tx = null;
Long folderID = null;
try {
tx = session.beginTransaction();
folderID = (Long) session.save(a_folder);
tx.commit();
}catch(HibernateException e)
{
if (tx != null)
tx.rollback();
log("Error");
e.printStackTrace();
}finally
{
session.close();
}
return(folderID);
}
public static Long addFile(Long folderID, Fichier a_file)
{
log("addFile");
Session session = factory.openSession();
//Load Dossier persistent object
Dossier l_folder = (Dossier) session.load(Dossier.class, folderID);
log("Folder@Name: " + l_folder.getName());
log("Folder@FilesCount: " + l_folder.getFiles().size());
//add the file
l_folder.addFile(a_file);
log("Folder@FilesCount: " + l_folder.getFiles().size());
session.flush();
return(a_file.getId());
}
public static void main(String arg[])
{
//Instantiate Dossier (a folder)
Dossier folder = new Dossier();
//Instantiate 4 Fichier objects (4 files)
Fichier file1, file2, file3, file4;
file1 = new Fichier();
file2 = new Fichier();
file3 = new Fichier();
file4 = new Fichier();
file1.setName("File1");
file2.setName("File2");
file3.setName("File3");
file4.setName("File4");
//Add files to the folder
folder.addFile(file1);
folder.addFile(file2);
folder.addFile(file3);
//Configure session factory
ManageDB.setup();
//Add folder to database
ManageDB.addFolder(folder);
}
}
Hibernate files (I used hibernate with XML, no annotations).
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="HibernateTestSessionFactory">
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/test</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>
</session-factory>
</hibernate-configuration>
Dossier.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20 nov. 2015 03:16:28 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.testhibernate.Dossier" table="DOSSIER">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<list name="files" table="FICHIER" access="field" cascade="all">
<key>
<column name="ID" />
</key>
<list-index></list-index>
<one-to-many class="com.testhibernate.Fichier" />
</list>
</class>
</hibernate-mapping>
Fichier.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20 nov. 2015 03:16:28 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.testhibernate.Fichier" table="FICHIER">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<many-to-one name="folder" class="com.testhibernate.Dossier" fetch="join">
<column name="FOLDER" />
</many-to-one>
</class>
</hibernate-mapping>
When I execute the program an error occurs:
ERROR Cannot add or update a child row: a foreign key constraint fails (
test
.fichier
, CONSTRAINTFKa0k27gcqnhentsb26vm3cwki0
FOREIGN KEY (ID
) REFERENCESdossier
(ID
))
When there is only one element in the ''files'' list, everything works fine.
Database model generated automatically
DOSSIER Table
+---------+-------------------------------------------------------
| Table | Create Table
+---------+-------------------------------------------------------
| dossier | CREATE TABLE `dossier` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`NAME` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
+---------+-------------------------------------------------------
1 row in set (0.00 sec)
FICHIER Table
-----------------------------------------------------------------------------------------+
| Table | Create Table
|
+---------+-------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------+
| fichier | CREATE TABLE `fichier` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`NAME` varchar(255) DEFAULT NULL,
`FOLDER` bigint(20) DEFAULT NULL,
`files_ORDER` int(11) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `FKgc8774xohnq2sadsw2bum3kn7` (`FOLDER`),
CONSTRAINT `FKa0k27gcqnhentsb26vm3cwki0` FOREIGN KEY (`ID`) REFERENCES `dossier` (`ID`),
CONSTRAINT `FKgc8774xohnq2sadsw2bum3kn7` FOREIGN KEY (`FOLDER`) REFERENCES `dossier` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
+---------+-------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------+
1 row in set (0.04 sec)
Thanks!
You are adding your Files before your Folder. But the File table has a foreign key pointing toward the Folder : it doesn't exist yet.
Just save your Folder before saving the Files.
This is not a Hibernate problem, this is a Database problem.
I finally figured out my problem.
Error was in Hibernate mapping, here's the correct version of Dossier and Folder mapping.
Dossier mapping file
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20 nov. 2015 03:16:28 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.testhibernate.Dossier" table="DOSSIER">
<id name="id" type="java.lang.Long">
<column name="FOLDER_ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<list name="files" table="FICHIER" access="field">
<key>
<column name="FOLDER_ID" />
</key>
<list-index></list-index>
<one-to-many class="com.testhibernate.Fichier" />
</list>
</class>
</hibernate-mapping>
Fichier mapping file
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20 nov. 2015 03:16:28 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.testhibernate.Fichier" table="FICHIER">
<id name="id" type="java.lang.Long">
<column name="FILE_ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<many-to-one name="folder" class="com.testhibernate.Dossier" fetch="join">
<column name="FOLDER_ID" />
</many-to-one>
</class>
</hibernate-mapping>
One to many ( Dossier -> Fichier )
The one to many relation specifies a key (FOLDER_ID).
Many to One ( Fichier -> Dossier )
The many to one relation need to know the ID of the other (FOLDER_ID).
The error in the first version of mapping was to name differently the columns ID ( ID in the one-to-many and FOLDER in the many-to-one) .
Reading Hibernate documentation helped me:
Hibernate Documentation goto section 23.3. Customer/Order/Product to see a simple example of how implement a one-to-many relation.
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.