【问题标题】:Spring AOP for database operation用于数据库操作的 Spring AOP
【发布时间】:2012-09-08 10:45:48
【问题描述】:

我在一个spring,hibernate项目中工作,数据库是oracle。我有用于持久性相关操作的 DAO 层。

在我的所有表中,我有create_dateupdate_date 列分别代表在表中插入和更新行时的时间戳。

有一个要求,我必须更新该特定表的上述两个时间戳列,只要发生任何插入/更新操作,请求就意味着该表。例如,如果我的 DAO 层有两种方法,例如 m1和 m2 分别负责影响 t1 和 t2 表。现在,如果调用 m1 方法,则 t1 表的时间戳列将被更新,即对于插入,create_date 列将被更新,对于任何更新,update_date 列将被更新。

我对 Spring AOP 有想法,所以我想用 AOP 来实现上述要求,但我不太确定是否可以使用 AOP 来实现。

如果我可以使用 AOP 来满足这个要求,请告诉我。如果可能的话,请向我提供如何实现它的输入。

【问题讨论】:

    标签: java spring spring-aop


    【解决方案1】:

    我已经使用 Spring AOP 为我的应用程序中的一个模块实现了更新日期功能。 PFB代码供您参考

    希望这会有所帮助。 我想知道是否也可以为变量设置切入点。我知道使用 spring 的方面 j 实现可能无法实现。但是任何解决方法的人:P

        **
        * @author Vikas.Chowdhury
        * @version $Revision$ Last changed by $Author$ on $Date$ as $Revision$
        */
       @Aspect
       @Component
    public class UpdateDateAspect
    {
        @Autowired
        private ISurveyService surveyService;
    
        Integer surveyId = null;
    
        Logger gtLogger = Logger.getLogger(this.getClass().getName());
    
        @Pointcut("execution(* com.xyz.service.impl.*.saveSurvey*(..)))")
        public void updateDate()
        {
    
        }
    
        @Around("updateDate()")
        public Object myAspect(final ProceedingJoinPoint pjp)
        {
    
            // retrieve the runtime method arguments (dynamic)
            Object returnVal = null;
            for (final Object argument : pjp.getArgs())
            {
    
                if (argument instanceof SurveyHelper)
                {
                    SurveyHelper surveyHelper = (SurveyHelper) argument;
                    surveyId = surveyHelper.getSurveyId();
    
                }
    
            }
            try
            {
                returnVal = pjp.proceed();
            }
            catch (Throwable e)
            {
                gtLogger.debug("Unable to use JointPoint :(");
            }
            return returnVal;
        }
    
        @After("updateDate()")
        public void updateSurveyDateBySurveyId() throws Exception
        {
            if (surveyId != null)
            {
                surveyService.updateSurveyDateBySurveyId(surveyId);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我会改用 Hibernate 拦截器,这就是它们的用途。例如,需要此类字段的实体可以实现以下接口:

      public interface Auditable {
          Date getCreated();
          void setCreated(Date created);
          Date getModified();
          void setModified(Date modified);
      }
      

      然后拦截器总是在保存时设置修改的字段,并且只在尚未设置时设置创建的字段。

      【讨论】:

        【解决方案3】:

        尽管您一直在为您的问题寻求 Spring AOP 解决方案,但我想指出,使用数据库触发器可以实现相同的结果,例如。 G。在INSERT 操作期间自动设置created 时间戳,在UPDATE 语句期间自动设置modified 时间戳。

        这可能是一个很好的解决方案,特别是如果不是所有的数据库调用都通过 AOP 捕获的逻辑(例如,当因为方法不符合模式而绕过切入点定义时,甚至使用独立 SQL 完全绕过代码时)客户端),这样即使有人从不同的应用程序更新条目,您也可以强制执行修改后的时间戳。

        不过,它的缺点是您需要在所有受影响的表上定义触发器。

        【讨论】:

        • 我一直想为这种事情在数据库中添加触发器。但是还有一个难题是您在数据库中放入了多少逻辑?我通常会在代码中包含所有逻辑,而在数据库中没有逻辑。你的方法是什么@axel-knauf?
        【解决方案4】:

        Spring AOP 应该可以使用@Before 建议。如果您将实体传递给创建方法,则建议设置 create_date 并设置更新方法 update_date。您可能需要考虑以下事项以使您的工作更轻松:

        • 让所有实体实现一个通用接口来设置create_dateupdate_date。这使您无需进行反思即可获得共同的建议。
        • 有一个命名约定来标识我们 DAO 上的创建和更新方法。这将使您的切入点更简单。

        【讨论】:

        • 但是,我怎么知道应该发生在哪个表?
        • 你说它适用于你所有的桌子。
        • 我的意思是,在我的 DAO 层中,假设我有两种方法,例如 m1 和 m2 分别影响 t1 和 t2 表。现在假设调用了 m1 方法,那么我的方面将被调用,它将负责更新时间戳列。但是我的方面将如何知道它必须执行哪个表?在这种情况下,它应该更新 t1 表..
        • 为什么切面需要知道插入的是哪个表?它唯一的职责是在你的 dao 将对象持久化到数据库之前在对象中设置时间戳
        • 见鬼,我什至认为你不需要求助于 AOP。如果你有一个负责将所有对象持久化到数据库中的通用接口,比如CommonDao,它具有saveupdatedelete 方法,那么只需设置时间戳就足够了。如果你没有这样的CommonDao,你真的应该考虑一下,因为它显着减少了你与hibernate的耦合。
        猜你喜欢
        • 2012-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多