代码之家  ›  专栏  ›  技术社区  ›  Jan Vladimir Mostert

对返回Hibernate对象的方法使用Spring的Cacable注释

  •  0
  • Jan Vladimir Mostert  · 技术社区  · 9 年前

    我昨天安装了Memcached,最终得到了Spring @Cachable 注释正在工作。。。

    这段代码完美缓存:

    @Component("CacheProcessor")
    public class CacheProcessor {
        @Cacheable(value = "defaultCache", key="'dateTime-'.concat(#anything)")
        public String getDateTime2(String anything) {
            Date d = new Date();
            String response = Long.toString(d.getTime());
            return response;
        }
    }
    

    我尝试了为每个请求调用的缓存方法:

    @org.springframework.cache.annotation.Cacheable(value="defaultCache", key="username")
    public static List<Session> findSessionByUserName(String username) {
    
        String hql = "SELECT o FROM Session AS o WHERE o.username=:username";
        TypedQuery<Session> query = Session.entityManager().createQuery(hql, Session.class);
        query.setParameter("username", username);
        return query.getResultList();
    
    }
    

    …但迎接我的是堆栈竞赛而不是缓存结果:

    java.lang.IllegalStateException: Post-processor tried to replace bean instance of type [com.ahp.core.model.Session] with (proxy) object of type [com.sun.proxy.$Proxy66] - not supported for aspect-configured classes!
        at org.springframework.beans.factory.wiring.BeanConfigurerSupport.checkExposedObject(BeanConfigurerSupport.java:168)
        at org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:140)
        at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:60)
        at org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:91)
        at com.ahp.core.model.Session.<init>(Session.java:20)
        at com.ahp.core.model.Session.entityManager_aroundBody0(Session.java:57)
        at com.ahp.core.model.Session.entityManager(Session.java:1)
        at com.ahp.core.processor.AccountProcessor.validateSession(AccountProcessor.java:545)
        at com.ahp.core.processor.WarehouseProcessor.consume(WarehouseProcessor.java:93)
        at com.ahp.core.processor.WarehouseProcessor.consume(WarehouseProcessor.java:1)
        at com.ahp.messaging.processor.AbstractRPCConsumer.onMessage(AbstractRPCConsumer.java:32)
        at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:228)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:756)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:679)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$001(SimpleMessageListenerContainer.java:82)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$1.invokeListener(SimpleMessageListenerContainer.java:167)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.invokeListener(SimpleMessageListenerContainer.java:1241)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:660)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1005)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:989)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:82)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1103)
        at java.lang.Thread.run(Thread.java:744)
    

    如果有帮助的话,这里有一个Session类的片段,它是由Spring Roo生成的,然后使用Push In重构,我去掉了所有AspectJ,所以现在它只是一个Java类:

    @Entity
    @Configurable
    //@RooJavaBean
    //@RooToString
    //@RooJpaActiveRecord
    public class Session {
    
        @PersistenceContext
        transient EntityManager entityManager;
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "id")
        private Long id;
    
        @Version
        @Column(name = "version")
        private Integer version;
    
        @ManyToOne
        private Account account;
    
        @ManyToOne
        private Company company;
    
        @Column(name = "qusername")
        private String username;
    
        ....
    

    如果我删除 Configurable 注释,实体管理器不会被注入 IllegalStateException 被抛出。

        public static final EntityManager entityManager() {
            EntityManager em = new Session().entityManager;
            if (em == null)
                throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
            return em;
        }
    

    如何使用缓存 aspect-configured 课程?

    如果这是不可能的,那么使其在没有方面的情况下工作的程序是什么(假设这将使其可计算)?

    工作解决方案

    必须创建SessionService接口:

    @RooService(domainTypes = {Session.class })
    public interface SessionService {
        public List<Session> findSessionByUserName(String username);
    }
    

    会话服务实现:

    @Component
    public class SessionServiceImpl implements SessionService {
        @Override
        @Cacheable(value="defaultCache", key="#username")
        public List<Session> findSessionByUserName(String username) {
            return Session.findSessionByUserName(username);
        }
    }
    

    必须将Session类修改为可序列化,并返回Roo注释。

    @Entity
    @RooJavaBean
    @RooToString
    @Configurable
    @RooJpaActiveRecord
    public class Session implements Serializable {
       ...
    }
    

    然后使用自动连线的SessionService:

    @Autowired
    SessionService sessionService;
    

    我现在可以使用缓存:

    sessionService.findSessionByUserName(...)
    
    1 回复  |  直到 9 年前
        1
  •  2
  •   jmvivo    9 年前

    问题是您试图将缓存添加到静态方法(Roo-ActiveRecord模式中的方法)。必须在bean方法上配置缓存层(非静态)。

    一种方法是使用Roo生成在实体层和Web层之间创建服务层(请查看 Roo documentation ). 该实用程序创建Spring bean,该bean调用Roo实体方法并修改Contollers方法以使用它。因此,您可以使用 @Cacheable 随时随地使用缓存。

    祝你好运