更新ACL时,JdbcMutableAclService + HSQLDB = BadSqlGrammarException

时间:2013-01-16 10:00:52

标签: java spring spring-security hsqldb

我正在使用Spring ACL和MySQL,它运行正常。但是,在集成测试中,我使用HSQLDB引擎,当我调用aclService.updateAcl(myAcl)时,它会抛出以下异常:

Caused by: org.springframework.jdbc.BadSqlGrammarException: 
  PreparedStatementCallback; bad SQL grammar 
  [insert into acl_entry (acl_object_identity, ace_order, sid, mask, granting,
  audit_success, audit_failure)values (?, ?, ?, ?, ?, ?, ?)]; nested exception is
  java.sql.SQLException: statement is not in batch mode
...
java.sql.SQLException: statement is not in batch mode
...
org.hsqldb.HsqlException: statement is not in batch mode

整个代码段是:

ObjectIdentity oi = new ObjectIdentityImpl(domainObject);
MutableAcl acl = aclService.createAcl(oi);
acl.setOwner(new PrincipalSid(SYSTEM_PRINCIPAL_SID));
if (parentObject != null) {
    Acl parent = aclService.readAclById(new ObjectIdentityImpl(parentObject));
    acl.setParent(parent);
}
aclService.updateAcl(acl);

aclService字段是类JdbcMutableAclService的实例。请注意,在MySQL上一切正常。

Spring 3.1.2.RELEASE。

修改 实际上只有在acl.getEntries()返回空列表时才抛出异常(因为刚刚创建了ACL - 它不包含ACE)。我通过扩展JdbcMutableAclService的默认实现并覆盖updateAcl()方法来修复问题,该方法通过在空列表上调用createEntries()来导致问题。我仍然不知道这个问题的真正原因,但我设法让它工作。这是我的快速解决方案:

@Override
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
    if (acl.getEntries().size() > 0) {
        return super.updateAcl(acl);
    }

    Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");

    // Change the mutable columns in acl_object_identity
    updateObjectIdentity(acl);

    // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc)
    return (MutableAcl)super.readAclById(acl.getObjectIdentity());
}

1 个答案:

答案 0 :(得分:0)

根据我的一般经验(老实说,从未尝试过使用HSQLDB的Spring ACL),并且根据this,当PreparedStatement与HSQLDB一起使用时,必须添加批处理。因此,我猜你无法在HSQLDB上测试Spring ACL。