使用Dropwizard dbi onDemand

时间:2016-12-08 17:09:08

标签: postgresql docker dropwizard jdbi

根据Dropwizard的观察,使用DBI.onDemand创建的DBI dao实例可以打开&根据需要关闭连接。我观察过一种情况,如果你在Docker中运行Dropwizard&让它闲置一天左右,我的daos无法重新连接到rdbms。

我正在做的是在启动时使用onDemand获取DAO实例一次&然后坚持应用程序的生命周期。这是使用onDemand的正确方法,还是每次我想运行查询时都应该获得一个新的DAO实例?

1 个答案:

答案 0 :(得分:0)

我只使用了dropwizard和MariaDB,但我认为postgresql的行为是类似的。 我在启动时创建一个dbi实例,并使用它为每个JDBI接口创建一个实例。这些JDBI实例在所有资源之间共享。

与Guice一起使用的裸骨示例如下所示:

假设您有一个JDBI接口UserQuery:

@RegisterMapper(UserMapper.class)
public interface UserQuery {

    @GetGeneratedKeys
    @SqlUpdate("INSERT INTO userData (email, role) values (:email, role)")
    long insertUser(@BindBean User user);

    @SqlQuery("SELECT * FROM userData WHERE id = :id")
    User getUserById(@Bind("id") long id);

假设您还有另一个JDBI接口CommentQuery。

在启动时,为UserQuery和CommentQuery创建一个dbi onDemand实例。创建一个注入器对象,并将这两个实例绑定到它们的类UserQuery.class和CommentQuery.class。从注入器对象创建单个实例UserResource并使用jersey注册它。 因此,您最终会得到一个UserQuery实例,一个CommentQuery实例和一个UserResource实例。

@Override
public void run(MyConfiguration conf, Environment env)  {
    Injector injector = Guice.createInjector(Stage.DEVELOPMENT, new AbstractModule() {
        @Override
        protected void configure() {
            DBIFactory factory = new DBIFactory();
            DBI dbi = factory.build(env, conf.getDatabase(), "mydb");
            UserQuery userQuery = dbi.onDemand(UserQuery.class);
            bind(UserQuery.class).toInstance(userQuery);
            CommentQuery commentQuery = dbi.onDemand(CommentQuery.class);
            bind(CommentQuery.class).toInstance(commentQuery);
        }
    });
    UserResource userResource = injector.getInstance(UserResource.class);
    env.jersey().register(userResource);
}

UserResource可能如下所示:

@Path("/user")
public class UserResource {
    private final UserQuery userQuery;
    private final CommentQuery commentQuery;

    @Inject
    public UserResource(UserQuery userQuery, CommentQuery commentQuery) {
        this.userQuery = userQuery;
        this.commentQuery = commentQuery;
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response createUser(User user) {
        long userId = userQuery.insertUser(user);
        Comment comment = new Comment();
        comment.setCreatorId(userId);
        comment.setTitle("Hello everyone!");
        commentQuery.insert(comment);
        return Response.ok().build();
    }
}

或者,如果您不想使用guice(删除UserResource中的@Inject注释)

@Override
public void run(MyConfiguration conf, Environment env) {
    DBIFactory factory = new DBIFactory();
    DBI dbi = factory.build(env, conf.getDatabase(), "mydb");
    UserQuery userQuery = dbi.onDemand(UserQuery.class);
    CommentQuery commentQuery = dbi.onDemand(CommentQuery.class);
    UserResource userResource = new UserResource(userQuery, commentQuery);
    env.jersey().register(userResource);
}

这与您所描述的非常相似。我也使用了docker和dropwizard,但到目前为止我还没有遇到过所描述的问题。