java - 使用 jUnit 在 Hibernate 和 Spring 中神奇地更新实体

标签 java spring hibernate junit

我有一个网络项目,其中使用Spring 3.1.1.RELEASE、Hibernate 4.2.0.Final、mysql版本'5.5 .19-enterprise-commercial-advanced-log' 和 junit 4.7

我正在进行单元测试,测试我的 CRUD 操作。

我做了几次测试,几乎都很好,问题出在组事件关系中,在更新测试中,我想创建一个和许多事件,设置列表(严格意义上的HashSet)并将组发送到服务,更新方法也是如此。 创建工作正常,但不能更新:(

类(class)

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
    ......

映射

<?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>

我的单元测试

@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();
        }
    }

}

服务

@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");
    }
}

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;
    }

当我运行测试更新时抛出此错误:

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

并记录

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

是的,group_idNOT NULL,但是为什么会发生此更新?

在多次测试我的代码注释时,假设每次产生此异常,他都会将其归因于我所做的事情。但不是。

事实上,将列更改为接受 null,并且我的测试运行良好,在我的单元测试和数据库中都重新表述了正确的情况。

我一直想知道为什么会发生这种情况,我从来没有做过这个神奇的更新,这就是我做错的地方,请我需要你的帮助。

最佳答案

问题是当这条指令执行时:

group.setEventos(new HashSet<Evento>(form.getEventos()));

有与该群组相关的新 Activity 。这意味着之前链接到该群组的事件不再与其链接。

为了打破数据库中的此链接,Hibernate 需要将外键 EVENT.group_id 更新为 null,这就是进行更新的原因。

之前链接到该组的事件将作为单独的实体继续存在于数据库中,而不附加到任何组。

这是因为 Event@Entity 而不是 @Embeddable,因此它可以存在而不与 相关组。但是将外键列设置为不可为空的排序与此相反,并导致 Hibernate 尝试更新不可为空的列。

然后需要更新映射,以使 Event 成为没有组就无法存在的 @Embeddable,或者将外键声明为可为空。

关于java - 使用 jUnit 在 Hibernate 和 Spring 中神奇地更新实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22570163/

相关文章:

java - HTTP 传输错误 : unable to find valid certification path to requested on tomcat

java - IntelliJ 中没有注释的 Spring 项目

java - NoSuchBeanDefinitionException : No bean named . ..DriverManagerDataSource 已定义

java - Hibernate物化不存在的实体

java - 在Spring Boot测试中未加载Gradle测试依赖项

java - Runnable 运行在哪个线程上?

java - Spring Boot 升级错误 - 名称为 org.springframework.transaction.config.internalTransactionalEventListenerFactory 的无效 bean 定义

java - JPA/hibernate 需要帮助 - 创建实体类的问题

java - JPA2 Criteria API : What is the difference between using Entity. 类和 from 子句中元模型的 EntityType

java - java中错误和未经检查的异常之间的区别?