Spring : Use Hibernate types without hibernate.cgf

2019-09-06 09:54发布

I am working on a Spring-MVC application which uses Hibernate as an ORM tool. We would like to encrypt some columns and for that I am using Jasypt. Now, for that I have to use the annotation @Type, but it requires that there should be a hibernate.cfg.xml file present. Unfortunately, I am not using hibernate.cfg.xml and my sessionFactory and all other configuration are defined in applicationServletContext.xml and root-context.xml.

These are the types I want to use : Filename : jasyptHibernateTypes.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <!-- VARCHAR, CLOB, TEXT based types -->

    <typedef name="encryptedString" class="org.jasypt.hibernate.type.EncryptedStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedBigDecimalAsString" class="org.jasypt.hibernate.type.EncryptedBigDecimalAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedBigIntegerAsString" class="org.jasypt.hibernate.type.EncryptedBigIntegerAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedBooleanAsString" class="org.jasypt.hibernate.type.EncryptedBooleanAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedByteAsString" class="org.jasypt.hibernate.type.EncryptedByteAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedCalendarAsString" class="org.jasypt.hibernate.type.EncryptedCalendarAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedDateAsString" class="org.jasypt.hibernate.type.EncryptedDateAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedDoubleAsString" class="org.jasypt.hibernate.type.EncryptedDoubleAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedFloatAsString" class="org.jasypt.hibernate.type.EncryptedFloatAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedIntegerAsString" class="org.jasypt.hibernate.type.EncryptedIntegerAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedLongAsString" class="org.jasypt.hibernate.type.EncryptedLongAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedShortAsString" class="org.jasypt.hibernate.type.EncryptedShortAsStringType">
        <param name="encryptorRegisteredName">jasyptHibernateEncryptor</param>
    </typedef>


    <!-- VARBINARY, BLOB based type -->
    <typedef name="encryptedBinary" class="org.jasypt.hibernate.type.EncryptedBinaryType">
        <param name="encryptorRegisteredName">jasyptByteHibernateEncryptor</param>
    </typedef>

    <!-- NUMERIC, NUMBER based types -->
    <typedef name="encryptedBigDecimal" class="org.jasypt.hibernate.type.EncryptedBigDecimalType">
        <param name="encryptorRegisteredName">jasyptBigDecimalHibernateEncryptor</param>
    </typedef>

    <typedef name="encryptedBigInteger" class="org.jasypt.hibernate.type.EncryptedBigIntegerType">
        <param name="encryptorRegisteredName">jasypBigIntegertHibernateEncryptor</param>
    </typedef>



</hibernate-mapping>

Here is my root-context.xml :

<context:component-scan base-package="com.journaldev.spring">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <context:property-placeholder location="classpath:application.properties"/>

    <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
                destroy-method="close">
        <beans:property name="driverClassName" value="org.postgresql.Driver"/>
        <beans:property name="url"
                        value="jdbc:postgresql://localhost:5432/dbname"/>
        <beans:property name="username" value="postgres"/>
        <beans:property name="password" value="password"/>
        <beans:property name="removeAbandoned" value="true"/>
        <beans:property name="removeAbandonedTimeout" value="20"/>
        <beans:property name="defaultAutoCommit" value="false"/>
    </beans:bean>

    <!-- Hibernate 4 SessionFactory Bean definition -->
    <beans:bean id="hibernate4AnnotatedSessionFactory"
                class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource"/>
        <beans:property name="packagesToScan" value="com.journaldev.spring.model"/>

        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
                <beans:prop key="hibernate.show_sql">false</beans:prop>
                <!--   <beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>
                   <beans:prop key="hibernate.order_updates">true</beans:prop>-->
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
                <beans:prop key="cache.use_second_level_cache">true</beans:prop>
                <beans:prop key="cache.use_query_cache">true</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>

    <beans:bean id="LoginServiceImpl" class="com.journaldev.spring.service.LoginServiceImpl"/>

    <task:annotation-driven/>

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

 <beans:bean id="stringEncryptor"  class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" lazy-init="false">
        <beans:property name="algorithm" value="PBEWithMD5AndDES" />
        <beans:property name="password" value="password" />
    </beans:bean>

    <beans:bean id="hibernateEncryptor" class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor" lazy-init="false">
        <!-- This property value must match "encryptorRegisteredName" used when defining hibernate user types -->
        <beans:property name="registeredName" value="jasyptHibernateEncryptor" />
        <beans:property name="encryptor" ref="stringEncryptor" />
    </beans:bean>

As you can see, my major config is in this file, and I have also put the interceptors here. I am getting this error :

Caused by: org.hibernate.MappingException: Could not determine type for: encryptedString
    at org.hibernate.cfg.annotations.SimpleValueBinder.fillSimpleValue(SimpleValueBinder.java:516)
    at org.hibernate.cfg.SetSimpleValueTypeSecondPass.doSecondPass(SetSimpleValueTypeSecondPass.java:42)
    at org.hibernate.cfg.Configuration.processSecondPassesOfType(Configuration.java:1472)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1420)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
    ... 98 more
Caused by: org.hibernate.annotations.common.reflection.ClassLoadingException: Unable to load Class [encryptedString]
    at org.hibernate.annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:60)
    at org.hibernate.cfg.annotations.SimpleValueBinder.fillSimpleValue(SimpleValueBinder.java:497)
    ... 108 more
Caused by: java.lang.ClassNotFoundException: encryptedString
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at org.hibernate.annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:57)
    ... 109 more

Model class:

 @Column(name = "mnotetext")
    @Type(type="encryptedString")
    private String mnotetext;

    @Column(name = "mnoteheadline")
    @Type(type="encryptedString")
    private String mnotetag;

What should I do to use the types without hibernate.cfg.xml. How to instruct hibernate that they are in this xml file. Thanks a lot. :-)

Update

Model class :

@TypeDef( name = "registeredName",
        defaultForType = org.jasypt.hibernate.type.EncryptedStringType.class,
        typeClass = org.jasypt.hibernate.type.EncryptedStringType.class)
@Entity
@Table(name = "groupnotes")
public class GroupNotes implements Serializable{
 @Column(name = "mnotetext")
    @Type(type="registeredName")
    private String mnotetext;

    @Column(name = "mnoteheadline")
    @Type(type="registeredName")
    private String mnotetag;
}

New error log :

Caused by: org.hibernate.MappingException: Unable to instantiate custom type: org.jasypt.hibernate.type.EncryptedStringType
    at org.hibernate.type.TypeFactory.custom(TypeFactory.java:218)
    at org.hibernate.type.TypeFactory.custom(TypeFactory.java:204)
    at org.hibernate.type.TypeFactory.byClass(TypeFactory.java:103)
    at org.hibernate.type.TypeResolver.heuristicType(TypeResolver.java:130)
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:340)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:322)
    at org.hibernate.mapping.Property.isValid(Property.java:241)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:496)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:270)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1360)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1851)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
    ... 98 more
Caused by: org.jasypt.exceptions.EncryptionInitializationException: If "encryptorRegisteredName" is not specified, then "password" (and optionally "algorithm" and "keyObtentionIterations") must be specified
    at org.jasypt.hibernate.type.AbstractEncryptedAsStringType.setParameterValues(AbstractEncryptedAsStringType.java:226)
    at org.hibernate.type.TypeFactory.injectParameters(TypeFactory.java:131)
    at org.hibernate.type.TypeFactory.custom(TypeFactory.java:214)
    ... 114 more

1条回答
Viruses.
2楼-- · 2019-09-06 10:19

I think your problem is how you declare your custom type. However it's possible to define type using annotations take a look at the documentation: 5.1.4.1.1. Type

@TypeDef( name = "registeredName",
    defaultForType = org.jasypt.hibernate.type.EncryptedStringType.class,
    typeClass = org.jasypt.hibernate.type.EncryptedStringType.class,
    parameters = {
        @Parameter(name="algorithm", value="PBEWithMD5AndTripleDES"),
        @Parameter(name="password", value="password"),
        @Parameter(name="keyObtentionIterations", value="1000")
    }
)

You can't use any bean in this.

查看更多
登录 后发表回答