I don't understand why my app drop Exception "Field 'Id_employeer' doesn't have a default value".
Id_employeer is my primary key, when I try to save any information to my database I got that exception, but, when I try just to read info from DB it's working.
I read topic on StackOverflow, but I still don't understand the answers in my app. I'm working with Hibernate 5.2.11.
My CharacterInfo.hbm.xml:
<?xml version="1.0"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="CharacterInfo" table="employees">
<id name="Id" column="id_employeer">
<generator class="native"/>
</id>
<property name="Login" column="employeer_login"/>
</class>
</hibernate-mapping>
My HibernateUtility:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import java.util.List;
public class HibernateUtility {
SessionFactory sessionFactory;
public void saving(Object object){
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save( object);
//session.save( new CharacterInfo().getLogin());
session.getTransaction().commit();
session.close();
}
public void reading(){
Session session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery("from CharacterInfo").list();
for ( CharacterInfo characterInfo : (List<CharacterInfo>) result ) {
System.out.println( "CharacterInfo (" + characterInfo.getLogin() + ") : " + characterInfo.getLogin() );
}
session.getTransaction().commit();
session.close();
}
protected void setUp() throws Exception {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure()
.build();
try {
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
} catch (Exception e) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
}
Next CharacterInfo class
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
#Entity
#Table( name = "employees")
public class CharacterInfo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Id_employeer")
private int id ;
#Column(name = "employeer_Login")
private String login;
public CharacterInfo() {}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
}
main class
public class main {
public static void main(String args[]) throws Exception {
HibernateUtility hibernateUtility = new HibernateUtility();
CharacterInfo characterInfo = new CharacterInfo();
characterInfo.setId(1);
characterInfo.setLogin("PawJaw");
hibernateUtility.setUp();
hibernateUtility.saving(characterInfo);
}
}
and in the end Exception
ERROR: Field 'Id_employeer' doesn't have a default value Exception in
thread "main" org.hibernate.exception.GenericJDBCException: could not
execute statement at
org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at
org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at
org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at
org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:178)
at
org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57)
at
org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
at
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2919)
at
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3490)
at
org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:626)
at
org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:280)
at
org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:261)
at
org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:306)
at
org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
at
org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
at
org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
at
org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at
org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at
org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at
org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at
org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:691)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:683) at
org.hibernate.internal.SessionImpl.save(SessionImpl.java:678) at
HibernateUtility.saving(HibernateUtility.java:17) at
main.main(main.java:10) Caused by: java.sql.SQLException: Field
'Id_employeer' doesn't have a default value at
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964) at
com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973) at
com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909) at
com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527) at
com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680) at
com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2487) at
com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at
com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2079)
at
com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2013)
at
com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5104)
at
com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1998)
at
org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
... 23 more
First of all, if you're using Hibernate annotations, you don't need to use Hibernate XML mapping files.
Your error is probably because of your database schema. The Id_employeer column is not auto-increment.
Related
I am tryin to write a very simple hibernate application. But when I am running the main method its throwing exception SQLSyntaxErrorException: Table 'testhibernate.employee' doesn't exist even though I have set hibernate.hbm2ddl.auto as "create".
Details are give below. Could you please help me on this ?
Class with main method :
package com.sr.main;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.sr.entity.Employee;
public class TestHibernate {
public static void main(String[] args) {
// TODO Auto-generated method stubu
Configuration config = new Configuration().configure("\\hibernate.cfg.xml");
SessionFactory factory = config.buildSessionFactory();
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
Employee emp1 = new Employee(111, "John",20000);
session.save(emp1);
tx.commit();
}
}
Entity class :
package com.sr.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Employee {
#Id
Integer empId;
String empName;
Integer empSal;
public Employee(Integer empId, String empName, Integer empSal) {
super();
this.empId = empId;
this.empName = empName;
this.empSal = empSal;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Integer getEmpSal() {
return empSal;
}
public void setEmpSal(Integer empSal) {
this.empSal = empSal;
}
}
config xml :
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name = "hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name = "hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name = "hibernate.connection.url">
jdbc:mysql://localhost/testHibernate
</property>
<property name = "hibernate.connection.username">
root
</property>
<property name = "hibernate.connection.password">
root
</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="show_sql">true</property>
<!-- List of XML mapping files -->
<mapping class = "com.sr.entity.Employee"/>
</session-factory>
</hibernate-configuration>
Exception :
java.sql.SQLSyntaxErrorException: Table 'testhibernate.employee'
doesn't exist at
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at
com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at
com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at
com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at
com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at
com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)
at
com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at
org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 20 more
MySql version : 5.5.50
Hibernate version : 5.4.25.Final
According to the documentation:
The entity class must have a public or protected no-argument constructor. It may define additional constructors as well.
So, you should correct your entity in the following way:
#Entity
public class Employee {
// ...
public Employee() {
}
public Employee(Integer empId, String empName, Integer empSal) {
this.empId = empId;
this.empName = empName;
this.empSal = empSal;
}
// ...
}
I've created 2 entity classes:
package entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "fr")
public class FR {
#Id
#Column(name = "id")
private String id;
#Column(name = "pid")
private String pId;
#Column(name = "pname")
private String pName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getpId() {
return pId;
}
public void setpId(String pId) {
this.pId = pId;
}
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
}
and
package entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "ar")
public class AR {
#Id
#Column(name = "id")
private String id;
#Column(name = "value1")
private String value1;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getValue1() {
return value1;
}
public void setValue1(String value1) {
this.value1 = value1;
}
}
and I'm trying to join these tables to fetch the record.
Query qry = session.createQuery("from FR left join AR on FR.pId = AR.id where FR.id=123 or FR.pId=123");
but getting an exception:
org.hibernate.QueryException: Unable to resolve path [FR.id], unexpected token [FR] [from entities.FR left join AR on FR.pId = AR.id where FR.id=123 or FR.pId=123]
and when I'm removing FR from the query
Query qry = session.createQuery("from FR left join AR on FR.pId = AR.id where id=123 or pId=123");
getting another exception:
org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [from entities.FR left join AR on FR.pId = AR.id where id=123 or pId=123]
I'm in a learning stage of Hibernate and don't know what to do now.
If you've any other info regarding Left Join or the other Joins then please share that too.
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>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/examples?zeroDateTimeBehavior=convertToNull</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">Root#123</property>
<property name="hibernate.show_sql">true</property>
<mapping class="entities.FR"/>
<mapping class="entities.AR"/>
</session-factory>
</hibernate-configuration>
Main Class
package hibernate.joins;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class HibernateJoins {
public static void main(String[] args) {
SessionFactory sessionFactory = getSessionFactory();
Session session = sessionFactory.openSession();
Query qry = session.createQuery("from FR left join AR on FR.pId = AR.id and ( FR.id=123 or FR.pId=123 )");
List list = qry.list();
list.forEach(System.out::println);
session.close();
sessionFactory.close();
}
public static SessionFactory getSessionFactory () {
SessionFactory sessionFactory = new Configuration().configure("configurations/hibernate.cfg.xml").buildSessionFactory();
return sessionFactory;
}
}
Since you are using ON clause in your query, therefore, you can not to use where clause separately. Just keep on adding the condition using AND or OR clause(whichever is applicable)
my problem is that one row added successfully but when adding more data it shows an error given below. there is duplicate entry but i want to insert two laptop data for the same student. Im beginner in hibernate please guide me sir.
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:190)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3587)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:103)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:453)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:345)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1218)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:421)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at HibRelation.App.main(App.java:43)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1040)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2794)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:187)
... 13 more
this is my student.java class
package HibRelation;
import java.util.*;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
#Entity
public class Student
{
#Id
private int RollName;
private String Lname;
private int marks;
#OneToMany(mappedBy = "std")
private List<Laptop> laptop = new ArrayList<Laptop>();
public int getRollName() {
return RollName;
}
public void setRollName(int RollName) {
this.RollName = RollName;
}
public String getLname() {
return Lname;
}
public void setLname(String Lname) {
this.Lname = Lname;
}
public int getMarks() {
return marks;
}
public void setMarks(int marks) {
this.marks = marks;
}
public List<Laptop> getLaptop() {
return laptop;
}
public void setLaptop(List<Laptop> laptop) {
this.laptop = laptop;
}
#Override
public String toString() {
return "Student{" + "RollName=" + RollName + ", Lname=" + Lname + ",
marks=" + marks + '}';
}
}
and this is my Laptop.java class
import java.util.*;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
#Entity
public class Laptop
{
#Id
private int id;
private String lname;
#ManyToOne
private Student std;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public Student getStd() {
return std;
}
public void setStd(Student std) {
this.std = std;
}
}
and this is main logic App.java
public class App {
public static void main(String[] args)
{
Student student=new Student();
student.setRollName(102);
student.setLname("Dinu");
student.setMarks(95);
Laptop lap= new Laptop();
lap.setId(1);
lap.setLname("hp");
student.getLaptop().add(lap);
lap.setStd(student);
Configuration con=new Configuration().configure().addAnnotatedClass(Student.class).addAnnotatedClass(Laptop.class);
StandardServiceRegistry registry=new StandardServiceRegistryBuilder().applySettings(con.getProperties()).build();
SessionFactory sfact=con.buildSessionFactory(registry);
Session session = sfact.openSession();
session.beginTransaction();
session.save(student);
session.save(lap);
session.getTransaction().commit();
}
}
Configuration.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>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedata</property>
<property name="hibernate.connection.username">root</property>
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
</session-factory>
</hibernate-configuration>
The error is caused by the duplication of a primary key in laptop table. A primary key is a column which uniquely identifies any row of the table. if you want to insert more than once keep changing the id value of laptop.So when you run the program for next time change the value of Id. Like
laptop.setId(2); //or something else which is not present in the table already
if you want to add the same laptop into a new student then retrieve that laptop first for e.g
Laptop theLaptop = Session.get(Laptop.class,theId) // theId is the laptopid
student.addLaptop(theLaptop);
session.save(student);
I would suggest using #GeneratedValue annotation on field id. Your error is due to violation of primary key constraint on field id. You must avoid setting id while saving objects ideally.
If you want to add same laptop object every time to different students, initialize your fields in laptop entity class, add a constructor and call that constructor every time while setting a laptop for any student.
I am trying to use Hibernate on my project << all sources if wanted, I try to create and save an object player on startup, I get the following error:
START SCRIPT!
org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.util.Date centaurus.domain.User.created] by reflection for persistent property [centaurus.domain.User#created] : User{id=0, email='test', created=Wed Jun 08 13:06:53 BST 2016}
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:43)
at org.hibernate.property.access.spi.GetterFieldImpl.getForInsert(GetterFieldImpl.java:58)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValuesToInsert(AbstractEntityTuplizer.java:521)
at org.hibernate.tuple.entity.PojoEntityTuplizer.getPropertyValuesToInsert(PojoEntityTuplizer.java:228)
at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValuesToInsert(AbstractEntityPersister.java:4701)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:254)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:682)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:674)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:669)
at centaurus.service.player.PlayerDAOimpl.saveUser(PlayerDAOimpl.java:32)
at centaurus.Dbmaintain.start(Dbmaintain.java:25)
at restx.factory.Factory.start(Factory.java:846)
at restx.RestxMainRouterFactory.build(RestxMainRouterFactory.java:450)
at restx.RestxMainRouterFactory.newInstance(RestxMainRouterFactory.java:70)
at restx.servlet.RestxMainRouterServlet.init(RestxMainRouterServlet.java:74)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:519)
at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:331)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:747)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:265)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:706)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:492)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:229)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:229)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:95)
at org.eclipse.jetty.server.Server.doStart(Server.java:277)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at restx.server.JettyWebServer.start(JettyWebServer.java:109)
at restx.server.JettyWebServer.startAndAwait(JettyWebServer.java:114)
at centaurus.AppServer.main(AppServer.java:30)
Caused by: java.lang.IllegalArgumentException: Can not set java.util.Date field centaurus.domain.User.created to centaurus.domain.User
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
at java.lang.reflect.Field.get(Field.java:379)
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:39)
... 40 more
2016-06-08 13:06:53,232 [main ] [ ] INFO restx.monitor.MetricsConfiguration - registering Metrics JVM metrics
I have stepped through my program and it seems to have a valid object passed the the hibernate save function, and somewhere inside it throws an error. I have tried removing the created field, at which point it then complains about a string field with the same error, trying to set it as a Player object itself.
here is my DAOimpl.class
package centaurus.dao.user;
import centaurus.domain.User;
import centaurus.service.HibernateUtils;
import restx.factory.Component;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import javax.inject.Named;
import java.util.List;
#Component
public class UserDAOimpl implements UserDAO {
private static HibernateUtils hibernateUtils;
public UserDAOimpl(#Named("HibernateUtils") HibernateUtils hibernateUtils) {
this.hibernateUtils = hibernateUtils;
}
public User saveUser(User user){
Session session = hibernateUtils.getFactory().openSession();
Transaction tx = null;
Integer playerID = null;
try{
tx = session.beginTransaction();
//playerID = (Integer) session.save(user);
session.save(user);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
return user;
}
public User getUser(int playerId){
Session session = hibernateUtils.getFactory().openSession();
try{
User user = (User)session.get(User.class, playerId);
return user;
}catch (HibernateException e) {
}finally {
session.close();
}
return null;
}
public List<User> getUsers(){
Session session = hibernateUtils.getFactory().openSession();
List<User> list = null;
try{
list = session.createCriteria(User.class).list();
}catch (HibernateException e) {
}finally {
session.close();
}
return list;
}
}
I have googled and googled and tried as many hibernate tutorials as i can find and I still have this issue. I don't understand why hibernate is trying to set a field as an object, I have my annotations.
incase its wanted here is my domain object player:
package centaurus.domain;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
#Entity
#Table(name="users")
public class User implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="USER_ID")
private int id = 0;
#Column(name="EMAIL")
private String email = "";
#Column(name="CREATED")
private Date created = null;
public User(){
Calendar cal = Calendar.getInstance();
this.created = cal.getTime();
};
public User(int id, String email, Date created) {
this.id = id;
this.email = email;
this.created = created;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", email='" + email + '\'' +
", created=" + created +
'}';
}
}
and here is the calling class:
package centaurus;
import centaurus.dao.user.UserDAO;
import centaurus.domain.User;
import restx.factory.AutoStartable;
import restx.factory.Component;
import javax.inject.Named;
#Component
public class DBMaintain implements AutoStartable{
private UserDAO userDAO;
public DBMaintain(#Named("UserDAOimpl") UserDAO userDAO) {
this.userDAO = userDAO;
}
public void start(){
System.out.println("START SCRIPT!");
//test
User p = new User();
p.setEmail("test");
userDAO.saveUser(p);
}
}
Please does anyone know how to solve this issue, thanks.
EDIT: (added sql)
CREATE TABLE Users(
USER_ID int NOT NULL AUTO_INCREMENT,
CREATED TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
EMAIL varchar(45) DEFAULT NULL,
PRIMARY KEY (USER_ID)
);
EDIT added hibernate config
/src/main/resources/hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection properties - Driver, URL, user, password -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/andromeda</property>
<property name="hibernate.connection.username">api</property>
<property name="hibernate.connection.password">apipassword</property>
<!-- Connection Pool Size -->
<property name="hibernate.connection.pool_size">1</property>
<!-- org.hibernate.HibernateException: No CurrentSessionContext configured! -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Outputs the SQL queries, should be disabled in Production -->
<property name="hibernate.show_sql">true</property>
<!-- Dialect is required to let Hibernate know the Database Type, MySQL, Oracle etc
Hibernate 4 automatically figure out Dialect from Database Connection Metadata -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping class="centaurus.domain.User"/>
</session-factory>
</hibernate-configuration>
Not sure if this is the answer but we will see!
Try replacing
CREATED TIMESTAMP DEFAULT CURRENT_TIMESTAMP
with
CREATED DATETIME DEFAULT CURRENT_DATETIME,
See the difference between Timestamp and Datetime in SQL is TIMESTAMP values are converted from the current time zone to UTC for storage, and converted back from UTC to the current time zone for retrieval. (This occurs only for the TIMESTAMP data type, not for other types such as DATETIME.)
If you store a TIMESTAMP value, and then change the time zone and retrieve the value, the retrieved value is different from the value you stored.
TimeStamp MySQL
While DATETIME represents a date (as found in a calendar) and a time (as can be observed on a wall clock),
Since you cannot store Java Date into a SQL TIMESTAMP object, either change the SQL TIMESTAMP to DATETIME or change the
private Date created;
to
private Timestamp created;
//And convert your Date to TimeStamp
public User(){
Date date = new Date();
created = new Timestamp(date .getTime());
}
Hope this helps!
remove the User class from the package centaurus
why?
On AppServer.main you have:
System.setProperty("restx.app.package", "centaurus");
this will make the restx recompile everything that's inside centaurus package and use this recompiled class, but apparently hibernate is retrieving the fields from the original class, not from the recompiled one
Here is the stacktrace that really matters:
Caused by: java.lang.IllegalArgumentException: Can not set java.util.Date field centaurus.domain.User.created to centaurus.domain.User
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
at java.lang.reflect.Field.get(Field.java:379)
The JVM is throwing an Exception because it cannot use the Field (that was retrieved by hibernate from the original compilation) at the class User (that was loaded by restx from the restx compilation)
Hibernate cannot transform to joda DateTime out of the box. Try to annotate your column with
#Type(type="org.joda.time.contrib.hibernate.PersistentDateTime")
See here for reference.
Looks like it is a bug in this version of Hibernate
HHH-10618
Try to use another one.
Your date field has to be annotated as follows:
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "creation", updatable = false, length = 19)
public Date getCreation() {
return this.creation;
}
public void setCreation(Date creation) {
this.creation = creation;
}
Be sure to rename column and name of the filed to match your project.
I started using Hibernate recently and I'm still a newbie, however, the error I'm facing doesn't seem to be simple.
My current environment is:
Windows 7
MySQL 5.1.49-community
mysql-connector-java-5.1.13-bin.jar
hibernate-distribution-3.6.0.Beta1
I'm following the "Hibernate in Action" book and did everything exactly the way it suggests.
When I try to delete a parent object (UserClass) of a many-to-one relation.
I expected that the parent object were deleted and all its child (User) too.
However, I got java.sql.BatchUpdateException, like quoted:
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
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:1215)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:382)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at netbeansproject.Main.testUserClassAndUsers(Main.java:42)
at netbeansproject.Main.main(Main.java:55)
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`lojatest`.`user`, CONSTRAINT `fk_User_UserClass1` FOREIGN KEY (`user_class_id`) REFERENCES `userclass` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1451)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 9 more
It seems to be related to MySQL Foreign Key constrants, specially regarding the "ON DELETE NO ACTION ON UPDATE NO ACTION", however, I'm not exactly an MySQL expert.
I've found some other questions about alike situation and I still couldn't find a fix for that.
Can anyone help me?
Thanks very much.
Here is relevant code:
User.java:
package domain;
public class User {
private String userName;
private String password;
private Boolean blocked;
private UserClass userClass;
public User() {
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Boolean getBlocked() {
return blocked;
}
public void setBlocked(Boolean blocked) {
this.blocked = blocked;
}
public UserClass getUserClass() {
return this.userClass;
}
public void setUserClass(UserClass userClass) {
this.userClass = userClass;
}
}
User.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="domain">
<class name="User" table="user">
<id
column="username"
name="userName"
type="string">
<generator class="assigned"/>
</id>
<property
column="password"
name="password"
not-null="true"
type="string"/>
<property column="blocked" name="blocked" type="boolean"/>
<many-to-one
name="userClass"
column="user_class_id"
class="UserClass"
not-null="true"/>
</class>
</hibernate-mapping>
UserClass.java
package domain;
import java.util.HashSet;
import java.util.Set;
public class UserClass {
private Long id;
private String title;
private String permissions;
private Set users = new HashSet();
public UserClass() {
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPermissions() {
return permissions;
}
public void setPermissions(String permissions) {
this.permissions = permissions;
}
public void setUsers(Set users) {
this.users = users;
}
public Set getUsers() {
return this.users;
}
public void addUser(User user) {
user.setUserClass(this);
this.users.add(user);
}
}
UserClass.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="domain">
<class
name="UserClass"
table="userclass">
<id
column="id"
name="id">
<generator class="native"/>
</id>
<property
column="title"
name="title"
not-null="true"
type="string"/>
<property
column="permissions"
name="permissions"
not-null="true"
type="string"/>
<set
name="users"
inverse="true"
cascade="all-delete-orphan">
<key column="user_class_id"/>
<one-to-many class="User"/>
</set>
</class>
</hibernate-mapping>
DatabaseFactory.java:
package Database;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class DatabaseFactory {
private static DatabaseFactory instance = null;
private SessionFactory sessionFactory;
public static DatabaseFactory getInstance() {
if (DatabaseFactory.instance == null) {
DatabaseFactory.instance = new DatabaseFactory().init();
}
return DatabaseFactory.instance;
}
public SessionFactory getSessionFactory() {
return this.sessionFactory;
}
public Session getSession() {
return this.sessionFactory.openSession();
}
private DatabaseFactory init() {
Configuration cfg = new Configuration();
cfg.addClass(domain.UserClass.class);
cfg.addClass(domain.User.class);
cfg.setProperties(System.getProperties());
cfg.configure();
SessionFactory sessions = cfg.buildSessionFactory();
sessionFactory = cfg.configure().buildSessionFactory();
return this;
}
}
Main.java (test class):
package netbeansproject;
import Database.DatabaseFactory;
import domain.*;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class Main {
public void testUserClassAndUsers() {
System.out.println("Testing Users and UserClasses...");
Session newSession = DatabaseFactory.getInstance().getSession();
System.out.println("1 - Creating UserClasses:");
Transaction t1 = newSession.beginTransaction();
UserClass uc1 = new UserClass();
uc1.setTitle("UserClass 1");
uc1.setPermissions("XYZ");
newSession.save(uc1);
t1.commit();
System.out.println("2 - Creating Users:");
Transaction t2 = newSession.beginTransaction();
User u1 = new User();
u1.setUserName("User 1");
u1.setPassword("Password 1");
u1.setBlocked(false);
u1.setUserClass(uc1);
newSession.save(u1);
User u2 = new User();
u2.setUserName("User 2");
u2.setPassword("Password 2");
u2.setBlocked(false);
u2.setUserClass(uc1);
newSession.save(u2);
t2.commit();
System.out.println("3 - Deleting UserClass (\"UserClass 1\"):");
Transaction t3 = newSession.beginTransaction();
newSession.delete(uc1);
t3.commit();
newSession.close();
}
public static void main(String[] args) {
Main instance = new Main();
instance.testUserClassAndUsers();
}
}
SQL Script to create DB (generated by MySQL Workbench):
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL';
DROP SCHEMA IF EXISTS `LojaTest` ;
CREATE SCHEMA IF NOT EXISTS `LojaTest` ;
SHOW WARNINGS;
USE `LojaTest` ;
-- -----------------------------------------------------
-- Table `LojaTest`.`UserClass`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `LojaTest`.`UserClass` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `LojaTest`.`UserClass` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`title` VARCHAR(45) NOT NULL ,
`permissions` VARCHAR(16) NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `id_UNIQUE` (`id` ASC) )
ENGINE = InnoDB;
SHOW WARNINGS;
-- -----------------------------------------------------
-- Table `LojaTest`.`User`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `LojaTest`.`User` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `LojaTest`.`User` (
`username` VARCHAR(10) NOT NULL ,
`password` VARCHAR(30) NOT NULL ,
`blocked` TINYINT(1) NOT NULL DEFAULT false ,
`user_class_id` INT UNSIGNED NOT NULL ,
PRIMARY KEY (`username`) ,
UNIQUE INDEX `id_UNIQUE` (`username` ASC)
)
ENGINE = InnoDB;
SHOW WARNINGS;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
Note I'm not creating any foreign key... however, after I run my code, a foreign key is created in the User table referencing the UserClass table id.
Before this test, I've tried the same SQL script, however with the following options for the User table:
CONSTRAINT `fk_User_UserClass1`
FOREIGN KEY (`user_class_id` )
REFERENCES `LojaTest`.`UserClass` (`id` )
ON DELETE CASCADE
ON UPDATE NO ACTION
And
CONSTRAINT `fk_User_UserClass1`
FOREIGN KEY (`user_class_id` )
REFERENCES `LojaTest`.`UserClass` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION
None of then worked.
Thanks again.
I've changed my approach and started using annotations.
At first, I had the same issue, but then I read a little about JPA's EntityManager and fixed the issue.
The issue was due to removing a UserClass in the same EntityManager's context that it was created.
I'm not getting back to this xml based mapping approach because it is not worthwhile (IMHO).
However, I think it may be solved using more than one Hibernate session. One to create the objects, and another to delete an object.
Hope it may help someone.
Thanks