表格提交数据时,外键导致出错


#1

有一个Table控件,DC的view用的_local,query的语句: <![CDATA[select e from lims_DictItem e where e.category=:category ORDER BY e.sort]]>

category是一个外键,界面上无需显示。做了一个action用于改变order字段的值。代码如下:

@Subscribe(“dictItemsTable.moveUp”)
protected void onItemsTableMoveUpActionPerformed(Action.ActionPerformedEvent event) {
DictItem currentItem = dictItemsTable.getSingleSelected();
if (currentItem==null)
return;
currentItem.setSort(currentItem.getSort()+1);
dataContext.merge(currentItem);
dataContext.commit();

执行的时候,第一次点击按钮是没有问题的,继续点击就直接报错了,category不允许为null。

java.sql.SQLIntegrityConstraintViolationException: Column ‘CATEGORY_ID’ cannot be null
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
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:970)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1109)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1057)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1377)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1042)
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:136)
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:136)
at com.haulmont.cuba.core.sys.jdbc.ProxyPreparedStatement.lambda$executeUpdate$1(ProxyPreparedStatement.java:39)
at com.haulmont.cuba.core.sys.jdbc.ProxyPreparedStatement$$Lambda$232/1138194105.call(Unknown Source)
at com.haulmont.cuba.core.sys.jdbc.ProxyStatement.executeSqlStatement(ProxyStatement.java:257)
at com.haulmont.cuba.core.sys.jdbc.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:39)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:942)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:1014)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:656)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:564)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2093)

看了下commit时候的对象,第一次category是null。后面再提交的时候category也是null,但是系统属性有值了,不知道为什么后面提交他就要去更新数据库里的category字段,第一次不会更新。


#2

DataContext 在 merge 数据时,会处理整个对象关系图。这个问题看上去更应该是数据的问题,既然是外键,当然不允许是null。建议通过修复数据解决问题。


#3

你没看明白吧?我用的_local,无论是界面还是后台我都没有去操作外键字段。我只是改了其他字段的值,然后提交。第一次提交成功后,第二次就提交报错。明显是框架底层什么地方出了问题!!!!


#4

这里是说的什么意思呢?category究竟有值还是null?


#5

意思是说,第一次提交的时候我查看实体属性category是null,但是可以提交成功!第二次提交的时候我查看实体属性category依然是null,但是提交失败了。
其实你直接用标准例子,子表使用_local视图,他是不会加载外键的,你用代码修改其他的字段,提交第一次成功,后面就没法提价了。


#6

你用的平台版本是多少? 我在 7.0.3 上没有重现这个问题。尽管每次 customerId 是null,merge Order都没有出错。
image


#7

用的是7.04,如您在7.04没错,麻烦把代码发我一下。


#8

你能提供一个可以复现问题的测试项目放到 GITHub吗?