如何在dropwizard中将http标头作为hibernate过滤器传递?

时间:2015-02-04 03:25:14

标签: hibernate http-headers jersey dropwizard hibernate-filters

我正在开发一个多租户应用程序,使用Hibernate的@Filter注释来隐式地按用户过滤实体(如本博客中所述:http://blog.lunatech.com/2011/03/04/play-framework-writing-multitenancy-application-hibernate-filters

租户ID在HTTP标头中传递,该标头由Jersey过滤器拦截,并使用以下代码在Hibernate会话中设置:

public class TenantFilter implements ContainerRequestFilter {
    private SessionFactory sessionFactory;

    public TenantFilter(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        String tenantId = request.getHeaderValue("X-TENANT-ID");
        Session currentSession = sessionFactory.openSession();
        currentSession.enableFilter("tenant").setParameter("tenant_id", tenantId);
        return request;
    }
}

但是,当DAO执行查询时,不会设置此过滤器参数,因为Resource方法和Filter中使用的hibernate会话不相同(使用currentSession导致会话不可用错误)

如何在与Dropwizard Resource方法相同的事务上下文中将Tenant参数传递给Dropwizard中的Hibernate会话? Jersey过滤器不在同一事务上下文中执行,因为@UnitOfWork在Resource方法上。

1 个答案:

答案 0 :(得分:0)

在游戏中,数据库会话由框架本身处理。 就像打开连接并设置当前线程的打开会话/使用@Transaction注释的人只能在那里使用。 您无法在代码中打开会话并关闭会话。

你必须像play的jpa插件一样创建自己的JPAPlugin。 为每个请求创建一个会话,并将其与当前线程(Threadlocal)关联,并在处理请求之前使用它。

在初始创建会话期间,您可以启用过滤器,在请求过程结束时,您可以禁用过滤器并关闭会话。

这是我们处理应用程序中的角色和权限的方式(使用Aspects)。

请看下面的帖子,它会给出一些关于如何创建自己的db插件的想法。

Play2 How to manage the transaction from the service layer instead of action layer?

希望这会给出一些暗示。

SessionImplementor currentSession =((SessionImplementor)em(key).getDelegate()); currentSession.enableFilter(" tenant")。setParameter(" tenant_id",tenantId);