Hibernate集成测试-Jaypt加密跳过参数



我使用的是使用Spring配置的Hibernate 4。我有一个简单的User类,它的密码属性用@Type annotation:进行了注释

@Entity
@Table(name = "Users")
public class User extends BaseEntity
{
    @Column(name = "UserName", unique = true, length = 31)
    @NotBlank(message = "User Name is required.")
    @Size(min = 3, max = 31, message = "User Name must be between 3 and 31 characters in length.")
    public String getUserName()
    {
        return userName;
    }
    public void setUserName(String userName)
    {
        this.userName = userName;
    }
    @Column(name = "Password", length = 511)
    @Type(type = "org.jasypt.hibernate4.type.EncryptedStringType", parameters = { @Parameter(name = "encryptorRegisteredName", value = "passwordEncryptor") })
    @NotBlank(message = "Password is required")
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
}

我正在运行一个集成测试,它使用HSQLDB作为存储引擎。测试只是创建一个User实例,并将其持久化

问题是,当用户被持久化时,密码列完全被排除在生成的SQL:之外

2829 [main] DEBUG org.hibernate.SQL  - insert into Users (Id, anonymous, Email, FirstName, LastName, Password, UserName) values (default, ?, ?, ?, ?, ?, ?)
2829 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [1] as [BOOLEAN] - false
2830 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [2] as [VARCHAR] - admin@testing.com
2830 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [3] as [VARCHAR] - admin
2830 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [4] as [VARCHAR] - admin
3069 [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder  - binding parameter [6] as [VARCHAR] - administrator

正如您所看到的,insert语句有6个占位符,而Hibernate只绑定了其中的5个参数。看看索引数字,你可以看到它正在跳过索引#5。

这是我的春季配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" value="jdbc:hsqldb:mem:ExampleTest" />
    <property name="initialSize" value="1" />
    <property name="maxActive" value="5" />
</bean>
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.my.entities" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>
<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven />
<bean id="hibernateStringEncryptor"
    class="org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor">
    <property name="registeredName">
        <value>passwordEncryptor</value>
    </property>
    <property name="algorithm">
        <value>PBEWithMD5AndTripleDES</value>
    </property>
    <property name="password">
        <value>MY_PASSWORD_HERE</value>
    </property>
</bean>

是我做错了什么,还是这是个bug?

编辑:似乎发生的并不是该列被跳过,而是被添加到insert语句中,只是没有被注销(令人讨厌)。真正的错误是生成的Password列具有错误的列长度(24而不是511)。

Caused by: org.hsqldb.HsqlException: data exception: string data, right truncation
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)

我将调试hibernate代码并弄清楚发生了什么。

调试Hibernate代码后,发现我的@Size验证约束覆盖了@Column(length=511)注释。因此,生成的列的长度为24,而不是511。

这可能是Hibernate中的一个错误,因为JPA规范(根据这个答案)说@Column注释应该用于DDL,而@Size属性应该仅用于验证。至少,@Column应该覆盖人们认为的@Size。尤其是在这种情况下,我使用的UserType会更改插入的字符串的大小。

最后,为了运行集成测试,我所做的只是告诉hibernate忽略集成测试项目中模式生成的验证,方法是添加"hibernate.validator.apply_to_ddl"属性:

<bean id="sessionFactory"
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.myentities" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.globally_quoted_identifiers">true</prop>
            <!-- THIS LINE HERE -->
            <prop key="hibernate.validator.apply_to_ddl">false</prop>
        </props>
    </property>
</bean>

最新更新