Spring JPA / Hibernate EmptyInterceptor不注入Entitymanager / Spring bean [英] Spring JPA/Hibernate EmptyInterceptor not injecting Entitymanager/Spring beans

查看:103
本文介绍了Spring JPA / Hibernate EmptyInterceptor不注入Entitymanager / Spring bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

专家/大师/好友



我们正在使用Spring 3.2,JPA 2,Hibernate 4.2组合并面对这个奇怪的空指针问题,同时尝试注入任何注释的spring将Bean放入EmtyInterceptor,如下所示。我们尝试了注释这个bean以及一个spring bean,但没有运气。



任何帮助解决这个难题在这里是高度赞赏。

  import javax.inject.Inject; 
import javax.inject.Named;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import org.springframework.transaction.annotation.Transactional;
...

@Named
@Transactional
public class AuditEmptyInterceptor extends EmptyInterceptor {
$ b $ / **
*
* /
private static final long serialVersionUID = 1L;

//未注入 - 空
@PersistenceContext
私有EntityManager entityManager;

//未注入 - 空
// @ PersistenceUnit
//私有EntityManagerFactory entityManagerFactory;

//未注入 - 空
// @注入
// private AuditHelper auditHelper;
$ b @Override
public boolean onSave(Object entity,Serializable id,Object [] currentState,
String [] propertyNames,Type [] types){

System.out.println(**********里面的OnSave()在审计空白拦截器******************);
if(entity instanceof xxAuditInterface || entity instanceof xxxCompBranchInterface){
for(int i = 0; i< propertyNames.length; i ++){
...
.. 。
// null entityManager - NPE here
javax.persistence.Query query = entityManager.createQuery(Select c From CompanyDO c where c.companyName =:companyName);
query.setParameter(companyName,xxx);
CompanyMasterDO companyMasterDO =(CompanyMasterDO)query.getSingleResult();
...
...
}
}
}

}

在应用程序中的其他地方,注入的工作就像一个魅力,没有任何问题。
这里是我们的applicationContext.xml

 <?xml version =1.0encoding =UTF-8 ?> 
< beans default-lazy-init =true
xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http:// www.w3.org/2001/XMLSchema-instance
xmlns:p =http://www.springframework.org/schema/p
xmlns:aop =http:// www。 springframework.org/schema/aop
xmlns:context =http://www.springframework.org/schema/context
xmlns:jee =http://www.springframework.org/ schema / jee
xmlns:tx =http://www.springframework.org/schema/tx
xmlns:util =http://www.springframework.org/schema/util
xmlns:sec =http://www.springframework.org/schema/security
xmlns:task =http://www.springframework.org/schema/task
xsi:schemaLocation =
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http:/ /www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http: //www.springframewo rk.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security- 3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http:// www .springframework.org / schema / mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/task http:// www.springframework.org/schema/task/spring-task-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring- AOP-3.2.xsd>


< context:annotation-config>< / context:annotation-config>

< context:component-scan base-package =com/>

< context:property-placeholder location =classpath *:hibernate.properties/>
< tx:annotation-driven />

< bean id =sessionFactoryclass =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< property name =dataSourceref =dataSource/>
< property name =packagesToScanvalue =com/>
< / bean>

class =org.springframework.jdbc.datasource.DriverManagerDataSource
p:driverClassName =com.mysql.jdbc.Driverp :url =jdbc:mysql:// localhost / rcent_rel_2
p:username =rootp:password =root/>

< bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
p:dataSource-ref =dataSourcep:jpaVendorAdapter-ref = jpaAdapter >
< property name =loadTimeWeaver>
< bean
class =org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver/>
< / property>
< property name =persistenceXmlLocationvalue =classpath *:META-INF / spring-persistence.xml/>
< / bean>

< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager
p:entityManagerFactory-ref =entityManagerFactory/>

class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
p:database =MYSQL
p: showSql =false
p:databasePlatform =org.hibernate.dialect.MySQL5Dialect/>

< \ beans>

我们的spring-persistence.xml如下。请注意,我在这里添加了Emptyinceptor属性。

 <?xml version =1.0encoding =UTF-8?> 

< persistence xmlns =http://java.sun.com/xml/ns/persistence
xmlns:xsi =http://www.w3.org/2001 / XMLSchema-instance
xsi:schemaLocation =http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0 .xsdversion =2.0>
< persistence-unit name =xxxtransaction-type =RESOURCE_LOCAL>
< class> com.xxx< / class>
...
...
<属性>
< property name =hibernate.ejb.interceptor
value =com.company.demo.audit.AuditEmptyInterceptor/>
< / properties>
< / persistence-unit>
< /余辉>

让我知道您对此的宝贵想法/提示。再次感谢您阅读本文的时间。

我也读过这篇文章在Hibernate的EmptyInterceptor中注入JPA的实体管理器。但看起来他们正在手动试图找到名称解决的bean,我觉得可能有其他方法。 AuditEmptyInterceptor 不是Spring管理的bean,它是由Hibernate实例化,所以你不能在其中注入依赖关系。



您可以使用静态委托来代替:

  public class StaticDelegateInterceptor扩展EmptyInterceptor {

private static Interceptor interceptor;

public static void setInterceptor(Interceptor interceptor){
StaticDelegate.interceptor = interceptor;

$ b $ public boolean onSave(Object entity,Serializable id,Object [] state,String [] propertyNames,Type [] types){
return StaticDelegate.interceptor.onSave(实体,id,状态,propertyNames,类型);
}
...
}

注册StaticDelegateInterceptor persistence.xml

 <持久性> 
< persistence-unit name =xxxtransaction-type =RESOURCE_LOCAL>
< class> com.xxx< / class>
...
...
<属性>
< property name =hibernate.ejb.interceptor
value =com.company.demo.audit.StaticDelegateInterceptor/>
< / properties>
< / persistence-unit>
< /余辉>

修改您当前的AuditEmptyInterceptor,以便使用StaticDelegateInterceptor注册自己:

  @Named 
@Transactional
public class AuditEmptyInterceptor extends EmptyInterceptor {

@PostConstruct
public void init(){
StaticDelagateInterceptor.setInterceptor(this);
}
...
}

最后确认您的 entityManagerFactory bean依赖于您的 auditEmptyInterceptor ,通过设置depends-on属性:

 < bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
p:dataSource-ref = dataSourcep:jpaVendorAdapter-ref =jpaAdapter
depends-on =auditEmptyInterceptor>
...
< / bean>


Experts/Gurus/Friends

We are working with Spring 3.2, JPA 2, Hibernate 4.2 combo and facing this weird null pointer issue while trying to inject any spring annotated beans into EmtyInterceptor implemented as shown below. We have tried annotating this bean as well as a spring bean but no luck.

Any help to solve this puzzle here is highly appreciated.

import javax.inject.Inject;
import javax.inject.Named;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import org.springframework.transaction.annotation.Transactional;
...

@Named
@Transactional
public class AuditEmptyInterceptor extends EmptyInterceptor {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    // Didnt inject - Null
    @PersistenceContext
    private EntityManager entityManager;

    // Didnt inject - Null
    //@PersistenceUnit
    //private EntityManagerFactory entityManagerFactory;

    // Didnt inject - Null
    //@Inject
    //private AuditHelper auditHelper;

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] currentState,
            String[] propertyNames, Type[] types) {

        System.out.println("**********inside OnSave() in Audit Empty Interceptor******************");
        if(entity instanceof xxAuditInterface || entity instanceof xxxCompBranchInterface){
            for (int i = 0; i < propertyNames.length; i++) {
         ...
         ...
         // Null entityManager - NPE here
        javax.persistence.Query query = entityManager.createQuery("Select c From CompanyDO c Where c.companyName =:companyName");
        query.setParameter("companyName", xxx);
        CompanyMasterDO companyMasterDO = (CompanyMasterDO) query.getSingleResult();
         ...
         ...
          }
         }
        }

 }

Everywhere else in the application the injection works like a charm without any issues. Here is our applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans default-lazy-init="true" 
xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" 
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">


<context:annotation-config></context:annotation-config> 

<context:component-scan base-package="com" />

<context:property-placeholder location="classpath*:hibernate.properties" />
<tx:annotation-driven />

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com"/>
 </bean>

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost/rcent_rel_2"
    p:username="root" p:password="root" />

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter">
    <property name="loadTimeWeaver">
        <bean
            class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    </property>
    <property name="persistenceXmlLocation" value="classpath*:META-INF/spring-persistence.xml" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    p:entityManagerFactory-ref="entityManagerFactory" />

<bean id="jpaAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    p:database="MYSQL" 
    p:showSql="false" 
    p:databasePlatform="org.hibernate.dialect.MySQL5Dialect"/>

<\beans>

And our spring-persistence.xml is below. Please note that I have added Emptyinceptor property here.

<?xml version="1.0" encoding="UTF-8"?>

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<persistence-unit name="xxx" transaction-type="RESOURCE_LOCAL">
    <class>com.xxx</class>
         ...
         ...
    <properties>
           <property name="hibernate.ejb.interceptor"
                       value="com.company.demo.audit.AuditEmptyInterceptor" />           
    </properties>
    </persistence-unit>
</persistence>

Let me know your valuable thoughts/tips on this. Once again thanks for your time to read this post.

Also I have read the post Injecting JPA's Entity Manager in Hibernate's EmptyInterceptor. But looks like they are manually trying to find the bean with name to resolve and I feel there could be some other way.

解决方案

The AuditEmptyInterceptor is not a bean managed by Spring, it is instantiated by Hibernate, so you cannot inject dependencies into it.

You can employ a static delegate instead:

public class StaticDelegateInterceptor extends EmptyInterceptor {

    private static Interceptor interceptor; 

    public static void setInterceptor(Interceptor interceptor) {
        StaticDelegate.interceptor = interceptor;
    }

    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
      return StaticDelegate.interceptor.onSave(entity, id, state, propertyNames, types);
    }
    ...
}

Register the StaticDelegateInterceptor on the persistence.xml

<persistence>
    <persistence-unit name="xxx" transaction-type="RESOURCE_LOCAL">
       <class>com.xxx</class>
       ...
       ...
       <properties>
          <property name="hibernate.ejb.interceptor"
                   value="com.company.demo.audit.StaticDelegateInterceptor" />           
       </properties>
   </persistence-unit>
</persistence>

Modify your current AuditEmptyInterceptor so that it register itself with the StaticDelegateInterceptor:

@Named
@Transactional
public class AuditEmptyInterceptor extends EmptyInterceptor {  

     @PostConstruct
     public void init() {
          StaticDelagateInterceptor.setInterceptor(this);
     }
     ...
}

And finally make sure your entityManagerFactory bean depends on your auditEmptyInterceptor by setting the depends-on attribute:

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter"
depends-on="auditEmptyInterceptor" >
...
</bean>

这篇关于Spring JPA / Hibernate EmptyInterceptor不注入Entitymanager / Spring bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆