2

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.

2
  • Are you sure you have recompiled your code after commenting out update method? It just can't be magically invoked. In order to make your update work fine, have you tried to set cascade properly to your events set? And last but not least, have you considered using JPA annotations instead of XML mapping? I wouldn't trust too much in autogenerated mapping Commented Mar 22, 2014 at 22:09
  • @MaciejWalkowiak first of all thank you for the reply, the idea that is not properly compiling seemed pretty accurate to me, I use STS and clean the project from the IDE, when followed without running clean with maven clean, but does not work, try deleting the file directly from the file system , build the project again and does not work. My team decides to always use mapping xml, I did it by hand mapping, but I'll check again Commented Mar 24, 2014 at 15:39

1 Answer 1

2
+100

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Oh!!! works, just a small thing group.setEventos(new HashSet<Evento>(form.getEventos())); is incorrect chrome change to because i have a extension with es-ar correc function is group.setEvents(new HashSet<Event>(form.getEvents())); sorry for my experiments -.-
I can not give bountry you up within 22 H, please remember me. And i need use this stackoverflow.com/questions/4753941/… when i use hbm mapping?
I am glad I could help. Yes that is correct, that link shows the XML equivalent to embeddable. have a look here at this link on how to award bounty meta.stackexchange.com/questions/16065/… thx
Ok thank you very much again, now everything in order

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.