我有一个网络项目,其中使用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_id
是NOT 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/