其他分享
首页 > 其他分享> > 春季-如何在没有活动会话的情况下将实体侦听器添加到JPA(EclipseLink)实体?

春季-如何在没有活动会话的情况下将实体侦听器添加到JPA(EclipseLink)实体?

作者:互联网

我正在弹簧豆中尝试执行以下操作:

@PostConstruct
public void registerTorchEntityListeners()
{
    Session session = entityManager.unwrap(Session.class);
    for (EntityType<?> entity : entityManager.getMetamodel().getEntities())
    {
        if (entity.getJavaType().isAnnotationPresent(TorchEntityListeners.class))
        {
             TorchEntityListeners annotation = (TorchEntityListeners) entity.getJavaType().getAnnotation(TorchEntityListeners.class);
             for (Class listenerClass : annotation.value())
             {
                 Map<String, DescriptorEventListener> map = applicationContext.getBeansOfType(listenerClass);
                 for (DescriptorEventListener listenerBean : map.values())
                 {
                     session.getClassDescriptor(entity.getClass()).getEventManager().addListener(listenerBean);
                 }
             }
        }
    }

}

问题是我得到以下异常,因为(我认为)我不在事务中,因此没有可用的会话来获取ClassDescriptor,因此我可以将侦听器添加到特定实体:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'torchEntityListenerConfigurer': Invocation of init method failed; nested exception is java.lang.IllegalStateException: No transactional EntityManager available
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:396)

基本上,我正在尝试执行等效于EclipseLink的操作:http://invariantproperties.com/2013/09/29/spring-injected-beans-in-jpa-entitylisteners/.我宁愿使用侦听器为实体添加注释,而不是执行以下操作:Injecting a Spring dependency into a JPA EntityListener.

有什么想法吗?

解决方法:

当然,我会在悬赏30分钟后解决:)

我终于通过从EntityManagerFactory中的连线获取EntityManager而不是使用@PersistenceContext将其注入到TorchEntityListenerConfigurer中来使其工作

这是有效的解决方案……效果很好!

这是配置:

<bean id="approvalEntityListener" class="com.prometheus.torchlms.core.activity.approval.ApprovalEntityListener">
    <property name="activityRepository" ref="activityRepository" />
    <property name="notificationFactory" ref="notificationFactory" />
    <property name="notificationService" ref="notificationService" />
</bean>
<bean id="springEntityListenerConfigurer" class="com.prometheus.torchlms.core.SpringEntityListenerConfigurer">
    <constructor-arg ref="entityManagerFactory" />
</bean>

这是魔术发生的地方(如果这对某人有用):

public class SpringEntityListenerConfigurer implements ApplicationContextAware
{
    private ApplicationContext applicationContext;
    private EntityManagerFactory entityManagerFactory;

    public SpringEntityListenerConfigurer(EntityManagerFactory entityManagerFactory)
    {
        this.entityManagerFactory = entityManagerFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException
    {
        this.applicationContext = applicationContext;
    }

    @PostConstruct
    public void registerTorchEntityListeners()
    {
        //entityManager.
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        Session session = entityManager.unwrap(Session.class);
        for (EntityType<?> entity : entityManagerFactory.getMetamodel().getEntities())
        {
            if (entity.getJavaType().isAnnotationPresent(SpringEntityListeners.class))
            {
                 SpringEntityListeners annotation = (SpringEntityListeners) entity.getJavaType().getAnnotation(SpringEntityListeners.class);
                 for (Class listenerClass : annotation.value())
                 {
                     Map<String, DescriptorEventListener> map = applicationContext.getBeansOfType(listenerClass);
                     for (DescriptorEventListener listenerBean : map.values())
                     {
                         ClassDescriptor classDescriptor = session.getClassDescriptor(entity.getJavaType());
                         if (null != classDescriptor)
                         {
                             classDescriptor.getEventManager().addListener(listenerBean);
                         }
                     }
                 }
            }
        }

    }
}

因此,现在我可以使用所需的任何侦听器将@SpringEntityListeners({ApprovalEntityListener.class})添加到所需的任何实体,这些侦听器可以是spring bean!

如果有帮助,这里是注释:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SpringEntityListeners
{
    Class<?>[] value();
}

标签:jpa-2-0,eclipselink,spring
来源: https://codeday.me/bug/20191029/1958626.html