i have a web project where is use Spring 3.1.1.RELEASE, Hibernate 4.2.0.Final , mysql version '5.5.19-enterprise-commercial-advanced-log' and junit 4.7
I'm doing my unit testing, i test my CRUD operations.
I made several test and almost all are fine, the problem is in group-event relationship, in update test, i want create a group and many events, set the list (HashSet in the strict sense) a send the group to the service, likewise the update method. Create works fine, but not update :(
Classes
public class Group implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer groupID;
private User user;
private Integer userID;
private User userManegement;
private Integer userManagementID;
private Date deteIni;
private Set<Event> events;
private Set<StatusGroup> status;
//get
//set
....
public class Event implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer eventID;
private Integer groupID;
private Date dateIni;
private Date dateTwo;
private String help;
private String commet;
private Group group;
//get
//set
......
Mapping
<?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 18/03/2014 09:58:25 AM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.my.dev.mysql.Group" table="Group">
<id name="groupID" type="java.lang.Integer">
<column name="id_group" />
<generator class="identity" />
</id>
<many-to-one name="user" column="user_id" foreign-key="id_user" class="com.my.dev.mysql.User"
fetch="join" update="false" insert="false">
</many-to-one>
<property name="userID" type="java.lang.Integer">
<column name="user_id" />
</property>
<many-to-one name="userManegement" column="user_management_id" foreign-key="id_user" class="com.my.dev.mysql.User"
fetch="join" update="false" insert="false">
</many-to-one>
<property name="userManagementID" type="java.lang.Integer">
<column name="user_management_id" />
</property>
<property name="deteIni" type="java.util.Date">
<column name="dete_ini" sql-type="DATE" not-null="true" />
</property>
<set name="events">
<key>
<column name="group_id" />
</key>
<one-to-many class="com.my.dev.mysql.Event" />
</set>
<set name="status">
<key>
<column name="group_id" />
</key>
<one-to-many class="com.my.dev.mysql.StatusGroup" />
</set>
</class>
</hibernate-mapping>
<?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 18/03/2014 09:58:25 AM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.my.dev.mysql.Event" table="EVENT">
<id name="eventID" type="java.lang.Integer">
<column name="id_event" />
<generator class="identity" />
</id>
<property name="groupID" type="java.lang.Integer" not-null="true">
<column name="group_id" />
</property>
<property name="dateIni" type="java.util.Date" not-null="true">
<column name="date_ini" sql-type="TIMESTAMP" not-null="true" />
</property>
<property name="dateTwo" type="java.util.Date" not-null="true">
<column name="date_two" sql-type="TIMESTAMP" not-null="true" />
</property>
<property name="help" type="java.lang.String">
<column name="help" not-null="true" />
</property>
<property name="commet" type="java.lang.String">
<column name="commet" not-null="true" />
</property>
<many-to-one name="group" column="group_id" foreign-key="id_group" class="com.my.dev.mysql.Group"
fetch="join" update="false" insert="false">
</many-to-one>
</class>
</hibernate-mapping>
My Unit Test
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners({ TransactionalTestExecutionListener.class, DependencyInjectionTestExecutionListener.class })
#ContextConfiguration(locations = { "/testEnvironment.xml" })
public class GroupServiceImplTest {
#Autowired
private GroupService groupService;
#Test //THIS TEST WORKS FINE
public void create() {
FormBeanGroup form = new FormBeanGroup();
form.setDate("24/03/2014");
List<Event> events = new ArrayList<Event>();
for (int i = 0; i < 8; i++) {
Event event = new Event();
event.setHelp("help -" + Randomizer.getNumSRandom());
event.setDateTwo(Calendar.getInstance().getTime());
Calendar now = Calendar.getInstance();
now.set(Calendar.DAY_OF_YEAR, now.get(Calendar.DAY_OF_YEAR) - i);
event.setDate(now.getTime());
event.setCommet("ubicacion ");
events.add(event);
}
form.setEvents(events);
try {
groupService.save(form);
} catch (GenericException e) {
e.printStackTrace();
}
}
#Test //THIS TEST WORKS FINE
public void get(){
Group group = groupService.getById(40);
System.out.println(group);
assertNotNull(group);
assertEquals(group.getStatus().get() , TypeGroup.ALFA);
}
#Test //THIS TEST WORKS FINE
public void delete(){
groupService.borrarEvents(41);
}
#Test // f*****in TEST
public void update() {
FormaCapturaGroup form = new FormaCapturaGroup();
form.setDate("24/03/2014");
form.setId(40);
List<Event> events = new ArrayList<Event>();
// for (int i = 0, k = 250; i < 8; i++, k++) { //fill events, but i comment, trying to find the error
form.setEvents(events);
try {
groupService.update(form);
} catch (GenericException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The service
#Transactional
public void update(FormBeanGroup form) throws GenericException {
Group group = groupDao.getById(form.getId());
if (group != null) {
//more code comment beacuse i trying to find the error
group.setEvents(new HashSet<Event>(form.getEvents())); //fix chrome grammar spelling
groupDao.update(group);
System.out.println("post");
}
}
The dao
public Group update(com.segurosargos.siga.modelo.mysql.Group group)
throws GenericException {
System.out.println("DAO{Update} ");
System.out.println(group);
//really 100 lines commet
//Believe me seriously.
//this is all code in update method
return null;
}
When i run the test update throws this error:
org.springframework.dao.DataIntegrityViolationException: could not perform addBatch; SQL [update EVENT set group_id=null where group_id=?]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not perform addBatch
at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:159)
at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:606)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:488)
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 $Proxy18.update(Unknown Source)
at com.my.dev.service.impl.GroupServiceImplTest.update(AgendaServiceImplTest.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.exception.ConstraintViolationException: could not perform addBatch
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:128)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:114)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:101)
at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:149)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:198)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:357)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:277)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:328)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1233)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:403)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:480)
... 36 more
Caused by: java.sql.BatchUpdateException: Column 'group_id' cannot be null
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1666)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1082)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:110)
... 48 more
And log
post
Hibernate:
update
EVENT
set
group_id=null
where
group_id=?
WARN : org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1048, SQLState: 23000
ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Column 'group_id' cannot be null
Yes group_id is NOT NULL but Why this update occurs?.
While testing my code comment much, provided each time this exception was produced, which he attributed to him something I had done. but not.
In fact change the column to accept null, and my test worked well, both within my unit test and database were restated things right.
I keep wondering why this happens, this magical update I never do, is what I'm doing wrong, please I need your help.
The problem is that when this instruction is executed:
group.setEventos(new HashSet<Evento>(form.getEventos()));
there are new events linked to the group. This means that the events previously linked to the group are no longer linked it to it anymore.
In order to break this link in the database Hibernate needs to update the foreign key EVENT.group_id to null, and that is the reason why the update is made.
The events previously linked to the group will go on existing as separate entities in the database, without being attached to any group.
This is because Event is an #Entity and not an #Embeddable, so it can exist without being related to a Group. But setting the foreign key column to not-nullable sort of goes against this and causes Hibernate to try to update a non nullable column.
The mapping then needs to be updated either to make Event an #Embeddable that cannot exist without a group, or declare the foreign key as nullable.
Related
I have created this new entity on my project, and mapped it by using an hibernate.hbm.xml file, but the query never returns anything despite rows being present inside the Table. I get no errors during deploy, so i think the mapping is correct, but i don't understand why it never returns anything.
This is my code:
Entity(the getters and setters are present, i just didn't add them for brevity)
package com.rmm.lpo.be.data.model.po;
import java.util.Date;
public class ManageIotRequest implements java.io.Serializable, com.enel.framework.be.data.model.po.PersistentObject{
/**
*
*/
private static final long serialVersionUID = 1L;
private Long id;
private Long lotCode;
private String transformerCode;
private String creatorUserId;
private Boolean pushLpDataRequired;
private String deviceSelectionMode;
private String fileName;
private String fileType;
private Boolean flDiscarded;
private Date completionDate;
private String errorCode;
private String detailedErrorCode;
private Date creationDate;
private Date pDate; ```
HBM MAPPING
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN">
<!-- Generated 24 nov 2021, 17:10:37 by Hibernate Tools 3.4.0.CR1 -->
-<hibernate-mapping>
-<class dynamic-insert="true" dynamic-update="true" schema="LPO" table="MANAGE_IOT_REQUEST" name="com.rmm.lpo.be.data.model.po.ManageIotRequest">
<meta inherit="false" attribute="implements">com.enel.framework.be.data.model.po.PersistentObject</meta>
<comment>User request for changing Iot desired configuration</comment>
-<id name="id" type="java.lang.Long">
<column name="ID"/>
-<generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
<param name="optimizer">none</param>
<param name="sequence_name">SQ_LPO_ID</param>
<param name="increment_size">1</param>
</generator>
</id>
-<property name="lotCode" type="java.lang.Long">
-<column name="LOT_CODE" not-null="true" scale="0" precision="12">
<comment>Identification of the Lot</comment>
</column>
</property>
-<property name="transformerCode" type="string">
-<column name="TRANSFORMER_CODE" length="64">
<comment>Identification of the Transformer</comment>
</column>
</property>
-<property name="creatorUserId" type="string">
-<column name="CREATOR_USER_ID" length="16">
<comment>Identification of the user creator</comment>
</column>
</property>
-<property name="pushLpDataRequired" type="java.lang.Boolean">
-<column name="PUSH_LP_DATA_REQUIRED">
<comment>Number that identify the acquisition type. 1 = PUSH, 0 =PULL</comment>
</column>
</property>
-<property name="deviceSelectionMode" type="string">
-<column name="DEVICE_SELECTION_MODE" length="16">
<comment>String that identify the device selection mode</comment>
</column>
</property>
-<property name="fileName" type="string">
-<column name="FILE_NAME" length="256">
<comment>Name of the file that is used for the request</comment>
</column>
</property>
-<property name="fileType" type="string">
-<column name="FILE_TYPE" length="16">
<comment>Type of data contained in the file used for deviceselection</comment>
</column>
</property>
-<property name="flDiscarded" type="java.lang.Boolean">
-<column name="FL_DISCARDED">
<comment>1 = discarded request, 0 = executed request</comment>
</column>
</property>
-<property name="errorCode" type="string">
-<column name="ERROR_CODE" length="16">
<comment>String for technical errors</comment>
</column>
</property>
-<property name="detailedErrorCode" type="string">
-<column name="DETAILED_ERROR_CODE" length="16">
<comment>String for technical errors</comment>
</column>
</property>
-<property name="completionDate" type="java.util.Date">
-<column name="COMPLETION_DATE">
<comment>date/time of creation of the LPO</comment>
</column>
</property>
-<property name="creationDate" type="java.util.Date">
-<column name="CREATION_DATE" not-null="true">
<comment>date/time of creation of the LPO</comment>
</column>
</property>
-<property name="pDate" type="java.util.Date">
-<column name="PDATE" not-null="true">
<comment>PDATE</comment>
</column>
</property>
</class>
</hibernate-mapping>
and this is my DAO:
package com.rmm.lpo.be.data.dao;
#Named("manageIotRequestDao")
public class ManageIotRequestDaoImpl extends TwoBeatBaseHibernateCrudDao<ManageIotRequest, Long>
implements ManageIotRequestDao {
private ManageIotRequestPOConverter manageIotRequestPOConverter;
private static final String LOT_SEQUENCE = "SQ_MANAGE_IOT_REQUEST_LOT_CODE";
#Inject
public ManageIotRequestDaoImpl(
#Named("manageIotRequestPOConverter") ManageIotRequestPOConverter manageIotRequestPOConverter) {
this.manageIotRequestPOConverter = manageIotRequestPOConverter;
}
#Override
public List<ManageIotRequestBO> getIotRequestByLotCode(Long lotCode) throws DaoException {
List<ManageIotRequestBO> result = new ArrayList<ManageIotRequestBO>();
try {
logger.debug("getIotRequestByLotId starts with input: lotCode = {}", lotCode);
Query query=sessionFactory.getCurrentSession().createQuery("select m from com.enel.twobeat.rmm.lpo.be.data.model.po.ManageIotRequest m where m.lotCode = :lotCode");
query.setParameter("lotCode", lotCode);
List<ManageIotRequest> listPo = query.list();
if (listPo != null) {
for (ManageIotRequest po : listPo) {
ManageIotRequestBO bo = (ManageIotRequestBO) manageIotRequestPOConverter.convertPOtoBO(po);
result.add(bo);
}
}
logger.debug("getIotRequestByLotId ends with result = {}", result);
} catch (HibernateException | ConverterException e) {
throw new DaoException(e.getMessage(), e);
}
return result;
}
}
What am i doing wrong? I've also ran a query with no where conditions, just a simple select star, but it still returns nothing.
I checked my hibernate.cfg.xml file, and i found out that i hadn't mapped the entity there with the mapped-resource tag..could this be the problem?
I have 2 tables, testInput and testCases and in testInput i have a FK with the id of the other table.
So basically the rows I want to delete are id of the input, id of the testCase, name and a description.
'43', '21', 'USERNAME', 'USERNAME'
'44', '21', 'PASSWORD', 'PASSWORD'
I tried to delete that row and I get
java.sql.SQLIntegrityConstraintViolationException: Cannot delete or
update a parent row: a foreign key constraint fails
(mydb.testInput, CONSTRAINT fk02 FOREIGN KEY (testCase)
REFERENCES testCases (idtestCase) ON DELETE NO ACTION ON UPDATE NO
ACTION)
I don't want to delete the record of testCase. I just want to delete the inputs of that testCase. What do I do?
code if u want...
List<TestInput> previousInputs = TestInput.getInputs(testCaseName);
for(TestInput in : previousInputs) {
Database.deleteObject(in);
}
//delete the object to the database
public static void deleteObject(Object object) {
SessionFactory factory = HibernateUtil.getSessionFactory();
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
session.delete(object);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
xml TestCases
<hibernate-mapping>
<class name="TestCase" table="testCases">
<meta attribute="class-description">
This class contains the testCases details.
</meta>
<id name="id" type="int" column="idtestCase">
<generator class="native"/>
</id>
<property name="name" column="name" type="string"/>
<many-to-one name="type" class="TestType" column="type" fetch="select" lazy="false"/>
<property name="data" column="data" type="binary"/>
<property name="amountOfInputs" column="amountOfInputs" type="int"/>
<property name="creationDate" column="creationDate" type="string"/>
<property name="createdBy" column="createdBy" type="string"/>
<many-to-one name="tellerConfig" class="TellerConfiguration" column="tellerConfig" fetch="select" lazy="false"/>
</class>
</hibernate-mapping>
xml testInput
<hibernate-mapping>
<class name="TestInput" table="testInput">
<meta attribute="class-description">
This class contains the testCases input details.
</meta>
<id name="id" type="int" column="idtestInput">
<generator class="native"/>
</id>
<property name="name" column="name" type="string"/>
<property name="description" column="description" type="string"/>
<many-to-one name="testCase" class="TestCase" column="testCase" fetch="select" cascade="all" lazy="false" />
</class>
Change the constraint on the foreign key fk02 from ´NO ACTION´ to 'SET NULL'
FOREIGN KEY (idtestcase)
REFERENCES testCases(idtestCase)
ON DELETE SET NULL
I'm trying get all the entries from Messages table using criteria
Criteria getCriteria = session.createCriteria(MessageAttributes.class);
List<MessageAttributes> unProcessedJcbMessagesList=getCriteria.list();
I'm getiing following exception when I'm trying run above criteria.
FieldId is the foreign key from AvailableFields(AvailableFieldsIs) table.
IllegalArgumentException occurred while calling setter for property [com.alu.jcb.model.MessageAttributes.fieldId (expected type = com.alu.jcb.model.AvailableFields)]; target = [com.alu.jcb.model.MessageAttributes#1cf3877], property value = [2]
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:123)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:713)
at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:362)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:4718)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:188)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1115)
at org.hibernate.loader.Loader.processResultSet(Loader.java:973)
at org.hibernate.loader.Loader.doQuery(Loader.java:921)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355)
at org.hibernate.loader.Loader.doList(Loader.java:2554)
at org.hibernate.loader.Loader.doList(Loader.java:2540)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370)
at org.hibernate.loader.Loader.list(Loader.java:2365)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:126)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1718)
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:380)
at com.alu.jcb.messageProcessor.Test.main(Test.java:23)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:68)
... 17 more
Beans
MessageAttributes.java
public class MessageAttributes {
private long messageAttributeId=1L;
private AvailableFields fieldId;
private String value;
//getters and setters
}
AvailableFields.java
public class AvailableFields {
private long availableFieldsId=1L;
private Instance instance;
private String fieldDisplayName;
//getters and setters
}
HBM files
MessageAttributes.hbm.xml
<hibernate-mapping package="com.alu.jcb.model">
<class name="MessageAttributes" table="MESSAGE_ATTRIBUTES">
<id name="messageAttributeId" column="message_attribute_id" type="long">
<generator class="sequence" />
</id>
<many-to-one name="fieldId" class="com.alu.jcb.model.AvailableFields" fetch="select">
<column name="field_id" not-null="true" />
</many-to-one>
<property name="value" type="string" column="value" />
</class>
</hibernate-mapping>
AvailableFields.hbm.xml
<hibernate-mapping package="com.alu.jcb.model">
<class name="AvailableFields" table="AVAILABLE_FIELDS">
<id name="availableFieldsId" column="available_fields_id" type="java.lang.Long">
<generator class="sequence" />
</id>
<many-to-one name="instance" class="com.alu.jcb.model.Instance" fetch="select">
<column name="instance_id" not-null="true" />
</many-to-one>
<property name="fieldDisplayName" type="string" column="field_display_name" not-null="true"/>
</class>
</hibernate-mapping>
Please help me
The error means something wrong with setter of fieldId. It should be like this
public void setFieldId(AvailableFields fieldId) {
this.fieldId=fieldId;
}
but it seems in your case incorrect class (guess long) is used in the setter.
SQLQuery sqlquery=session.createSQLQuery(queryString);
sqlquery.addScalar("fieldId ", IntegerType.INSTANCE);
I was receiving this error of
IllegalArgumentException occurred while calling setter for property
Version (type expected is Long but received 0)
because instead of using
Query query = sess.createSQLQuery(sqlQueryStr).addEntity(instance.getClass().getName());
retval = query.list();
I was doing
Query query = sess.createSQLQuery(sqlQueryStr)
.setResultTransformer(Transformers.aliasToBean(instance.getClass()));
retval = query.list();
In case it helps anyone.
I have 2 tables: Trip and Place (Many-To-One) and my problem is that when I add 2 trips with different data but the same place, it adds me 2 records to Trip table and 2 records into Place table, while it should add just one record into Place.
For example I had 2 trips with different dates but they were in the same place - Italy, Rome. So there should be only one record in Place with these data: Italy, Rome.
How can I avoid such behaviour in my application?
Trip class:
public class Trip implements java.io.Serializable {
private int idTrip;
private int idHotel;
private Date date;
private int cost;
private int profit;
private String organisator;
private int period;
private String food;
private String transport;
private int persons;
private int kidsAmount;
private String ownerName;
private String ownerLastName;
private Place place;
+ constructors, get() and set() methods,
Place class:
public class Place implements java.io.Serializable {
private int idPlace;
private String country;
private String city;
private String island;
private String information;
private Set<Trip> trips;
+ constructors, get() and set() methods,
Trip mapping file:
<hibernate-mapping>
<class name="pl.th.java.biuro.hibernate.Trip" table="Trip">
<id column="idTrip" name="idTrip" type="int">
<generator class="native"/>
</id>
<property column="date" name="date" type="date"/>
<property column="cost" name="cost" type="int"/>
<property column="profit" name="profit" type="int"/>
<property column="organisator" name="organisator" type="string"/>
<property column="period" name="period" type="int"/>
<property column="food" name="food" type="string"/>
<property column="transport" name="transport" type="string"/>
<property column="persons" name="persons" type="int"/>
<property column="kidsAmount" name="kidsAmount" type="int"/>
<property column="idHotel" name="idHotel" type="int"/>
<many-to-one fetch="select" name="place" class="pl.th.java.biuro.hibernate.Place">
<column name="idPlace" not-null="true"></column>
</many-to-one>
</class>
</hibernate-mapping>
Place mapping file:
<hibernate-mapping>
<class name="pl.th.java.biuro.hibernate.Place" table="Place">
<id column="idPlace" name="idPlace" type="int">
<generator class="native"/>
</id>
<property column="country" name="country" type="string"/>
<property column="city" name="city" type="string"/>
<property column="island" name="island" type="string"/>
<property column="information" name="information" type="string"/>
<set name="trips" table="Trip" inverse="true" lazy="true" fetch="select">
<key>
<column name="idPlace" not-null="true" />
</key>
<one-to-many class="pl.th.java.biuro.hibernate.Trip" />
</set>
</class>
</hibernate-mapping>
I also add some screenshot with my MySQL database, maybe there is some issue which not allow me to do this properly:
MySQL database
EDIT: Added one-to-many relation in Place mapping file and Set in Place class, but still got the same problem.
EDIT2: Adding code with persisting entites into database:
Session session = DatabaseConnection.getFactory().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
trip.setPlace(place);
session.save(place);
session.save(trip);
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
System.out.println("Exception found while adding new trip: " + e.getMessage());
e.printStackTrace();
} finally {
session.close();
}
But I am still having the same problem... I add one trip with place A, then in next step I add another trip with the same same, and here is what I get:
EDIT3: Creating Trip and Place objects:
Trip trip = null;
Place place = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateInString = tripDateField.getText();
java.util.Date date = null;
try {
date = sdf.parse(dateInString);
place = new Place(tripCountryField.getText(), tripCityField.getText(), tripIslandField.getText(), tripPlaceInfoTextArea.getText());
int period = 0, persons = 0, kidsAmount = 0;
//W razie braku niewymaganych liczbowych danych ustawiane są wartości -1
if (tripPeriodField.getText().equals("")) {
period = -1;
}
if (tripPersonsField.getText().equals("")) {
persons = -1;
}
if (tripKidsAmountField.getText().equals("")) {
kidsAmount = -1;
}
trip = new Trip(new Date(date.getTime()), Integer.parseInt(tripCostField.getText()), Integer.parseInt(tripProfitField.getText()),
tripOrganisatorField.getText(), period, tripFoodField.getText(), tripTransportField.getText(),
persons, kidsAmount, tripClientNameField.getText(), tripClientLastNameField.getText());
} catch (ParseException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
try {
date = sdf.parse("0000-00-00");
} catch (ParseException ex1) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex1);
}
} catch (NumberFormatException e) {
place = new Place("111", "111", "111", "111");
trip = new Trip(null, WIDTH, WIDTH, dateInString, WIDTH, dateInString, dateInString, WIDTH, ABORT, dateInString, dateInString);
System.out.println("Exception while getting trip / place data: " + e.toString());
}
dataEdition.addTrip(trip, place, dataEdition.validateTripData(trip, place), addRemoveSearchTripDialog);
I get these objects data from textFields and parse them to int if needed, so that should be ok I guess. After this I pass these 2 objects into another method where I persist them into database.
It looks like you create a NEW place on every submission.
Place place = new Place(tripCountryField.getText(), tripCityField.getText(), tripIslandField.getText(), tripPlaceInfoTextArea.getText());
and then you expect Hibernate to somehow magically determine that you may actually want to work with an existing entry in the database.
This will not work.
If the submitted place already exists then you need somehow to load the existing persistent entity and work with that.
You can either fix this on the front-end by allowing user to select an existing place and sending through the ID for that or you query for a matching place
on form submission.
e.g.
Place place = myDatabaseService.findPlace(country, name ...) //does not account for misspellings
if(place == null){
place = new Place(tripCountryField.getText(), tripCityField.getText(), tripIslandField.getText(), tripPlaceInfoTextArea.getText());
}
I've tried this one, and it is not making any duplicates:
And creation of the two classes and tables in DB, I created two mapping files in the same package as the classes.
The places mapping:
<hibernate-mapping package="pl.th.java.biuro.hibernate">
<class name="Place" table="PLACE">
<id name="idPlace" type="java.lang.Long" column="ID_PLACE">
<generator class="native">
</generator></id>
<set name="trips" table="Trip" inverse="true" lazy="true" fetch="select">
<key>
<column name="idPlace" not-null="true">
</column></key>
<one-to-many class="pl.th.java.biuro.hibernate.Trip">
</one-to-many></set>
</class>
</hibernate-mapping>
And the trip mapping:
<hibernate-mapping package="pl.th.java.biuro.hibernate">
<class name="Trip" table="TRIP">
<id name="idTrip" type="java.lang.Long" column="ID_TRIP">
<generator class="native">
</generator></id>
<many-to-one name="place" class="pl.th.java.biuro.hibernate.Place" fetch="select">
<column name="idPlace" not-null="true">
</column></many-to-one>
</class>
</hibernate-mapping>
I have seen, that your trip id is not generated on your table? Is that correct? And your naming convention is a bit error-prone. Try to name db tables uppercase and the set variable in class Place to maybe trips. In your mappings you mapped the id to an int. Most Databases map it to long, so maybe there is an error too.
I think your entities need to override hashcode() and equals() methods to be able to recognize their uniqueness.
I am using hibernate in my java program and I got some troubles using it ..
Here is my xml:
<hibernate-mapping>
<class name="revEngMapping.TestNetwork" table="testNetwork">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="networkElementId" type="string">
<column name="networkElement_id" length="45" />
</property>
<property name="date" type="string">
<column name="Date" length="45" />
</property>
<property name="oid" type="string">
<column name="Oid" length="150" />
</property>
<property name="value" type="string">
<column name="Value" length="200" />
</property>
</class>
here is my java class:
public class TestNetwork implements java.io.Serializable {
private Integer id;
private String networkElementId;
private String date;
private String oid;
private String value;
public TestNetwork() {
}
public TestNetwork(String networkElementId, String date, String oid,
String value) {
this.networkElementId = networkElementId;
this.date = date;
this.oid = oid;
this.value = value;
}
Then its just getters and setters, and in my main, I just want to display it:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Criteria crit = session.createCriteria(TestNetwork.class);
List resultList=crit.list();
for(int i=0;i<resultList.size();i++)
System.out.println(((TestNetwork)resultList.get(i)).getId()+" "+((TestNetwork)resultList.get(i)).getDate());
session.getTransaction().commit();
In my console it says that I have an SQL error ..
10:20:54,626 WARN JDBCExceptionReporter:233 - SQL Error: 1064, SQLState: 42000
10:20:54,628 ERROR JDBCExceptionReporter:234 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.testNetwork this_' at line 1
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2536)
Hope s.one can help. thanks
mysql requires you to use backticks `` when accessing table names & columns, please back ticks while defining
eg..
<property name="someProperty" column="`dbColumnName`"/>
this should solve your problem..
Anantha Sharma