如何在dropwizard上使用guice自动连接HibernateBundle?

我试图用guice / dropwizard配置hibernatebundle并需要帮助。 我使用hubspot / dropwizard-guice / 0.7.0第三方库以及dropwizard lib。

下面的代码显然不会工作,需要帮​​助才能搞清楚。 我如何重写这个,以便hibernatebundle和最终的会话工厂自动注入任何需要它的bean。

MyApplication.java

public class MyApplication extends Application { private final HibernateBundle hibernateBundle = new HibernateBundle(MyModel.class) { @Override public DataSourceFactory getDataSourceFactory(MyAppConfiguration configuration) { return configuration.getDataSourceFactory(); } }; @Override public void initialize(Bootstrap bootstrap) { bootstrap.addBundle(hibernateBundle); // ??? bootstrap.addBundle( GuiceBundle.newBuilder() .addModule(new MyAppModule()) .enableAutoConfig(getClass().getPackage().getName()) .setConfigClass(MyAppConfiguration.class) .build() ); } } 

MyAppModule.java

 public class MyAppModule extends AbstractModule { @Provides public SessionFactory provideSessionFactory(MyAppConfiguration configuration) { // really wrong as it creates new instance everytime. return configuration.getHibernateBundle().getSessionFactory(); // ??? } } 

MyAppConfiguration.java

 public class MyAppConfiguration extends Configuration { @Valid @NotNull private DataSourceFactory database = new DataSourceFactory(); @JsonProperty("database") public DataSourceFactory getDataSourceFactory() { return database; } @JsonProperty("database") public void setDataSourceFactory(DataSourceFactory dataSourceFactory) { this.database = dataSourceFactory; } // ??? public HibernateBundle getHibernateBundle() { return new HibernateBundle(MyModel.class) { @Override public DataSourceFactory getDataSourceFactory(MyAppConfiguration configuration) { return database; } }; } } 

以下是我最终的表现。 我从来没有从这里或邮件列表得到答案,所以我会考虑这种hackish,可能不是正确的方法,但它适用于我。

在我的模块中(扩展了abstractmodule):

 private final HibernateBundle hibernateBundle = new HibernateBundle(MyModel.class) { @Override public DataSourceFactory getDataSourceFactory(MyConfiguration configuration) { return configuration.getDataSourceFactory(); } }; @Provides public SessionFactory provideSessionFactory(MyConfiguration configuration, Environment environment) { SessionFactory sf = hibernateBundle.getSessionFactory(); if (sf == null) { try { hibernateBundle.run(configuration, environment); } catch (Exception e) { logger.error("Unable to run hibernatebundle"); } } return hibernateBundle.getSessionFactory(); } 

修订:

 public SessionFactory provideSessionFactory(MyConfiguration configuration, Environment environment) { SessionFactory sf = hibernateBundle.getSessionFactory(); if (sf == null) { try { hibernateBundle.run(configuration, environment); return hibernateBundle.getSessionFactory(); } catch (Exception e) { logger.error("Unable to run hibernatebundle"); } } else { return sf; } } 

我认为显式运行(配置,环境)调用(在@StephenNYC提供的答案中)有点奇怪,所以挖得更深一些。 我发现dropwizard-guice中的AutoConfig没有正确设置ConfiguredBundle(HibernateBundle就是这样一种类型)。

从https://github.com/HubSpot/dropwizard-guice/pull/35开始 ,代码现在看起来像这样:

 @Singleton public class MyHibernateBundle extends HibernateBundle implements ConfiguredBundle { public MyHibernateBundle() { super(myDbEntities(), new SessionFactoryFactory()); } private static ImmutableList> myDbEntities() { Reflections reflections = new Reflections("com.acme"); ImmutableList> entities = ImmutableList.copyOf(reflections.getTypesAnnotatedWith(Entity.class)); return entities; } @Override public DataSourceFactory getDataSourceFactory(NoxboxConfiguration configuration) { return configuration.getMyDb(); } } @Provides public SessionFactory sessionFactory(MyHibernateBundle hibernate) { return checkNotNull(hibernate.getSessionFactory()); } 

这背后的魔力是MyHibernateBundle实现了ConfiguredBundle,其中dropwizard-guice现在自动拾取并实例化。

这是我解决它的方式:
将Hibernate包放在guice模块中,并将bootstap对象作为guice模块构造函数的参数传递,以便可以将hibernate包添加到其中。
配置可以保持与使用没有guice的hibernate-bundle完全一样。
我使用了dropwizard-hibernate v0.7.1和dropwizard-guice v0.7.0.3

MyAppModule.java:

 public class MyAppModule extends AbstractModule { private final HibernateBundle hibernateBundle = new HibernateBundle(MyModel.class) { @Override public DataSourceFactory getDataSourceFactory(MyAppConfiguration configuration) { return configuration.getDataSourceFactory(); } }; public MyAppModule(Bootstrap bootstrap) { bootstrap.addBundle(hibernateBundle); } @Override protected void configure() { } @Provides public SessionFactory provideSessionFactory() { return hibernateBundle.getSessionFactory(); } } 

MyApplication.java:

 public class MyApplication extends Application { @Override public void initialize(Bootstrap bootstrap) { bootstrap.addBundle( GuiceBundle.newBuilder() .addModule(new MyAppModule(bootstrap)) .enableAutoConfig(getClass().getPackage().getName()) .setConfigClass(MyAppConfiguration.class) .build() ); } @Override public void run(final MyAppConfiguration configuration, final Environment environment) throws Exception { } } 

MyAppConfiguration.java:

 public class MyAppConfiguration extends Configuration { @Valid @NotNull @JsonProperty("database") private DataSourceFactory database = new DataSourceFactory(); public DataSourceFactory getDataSourceFactory() { return database; } } 

我没有在dropwizard中使用hibernate,但我使用过Guice,你真的只需要担心MyAppModule。 这就是魔术将要发生的地方:

 public class MyAppModule extends AbstractModule { @Singleton @Provides public SessionFactory provideSessionFactory(MyAppConfiguration configuration) { HibernateBundle hibernate = new HibernateBundle(MyModel.class) { @Override public DataSourceFactory getDataSourceFactory(MyAppConfiguration configuration) { return configuration.getDataSourceFactory(); } } return hibernate.getSessionFactory(); } } 

(有关多个类,请参见此处 )

MyAppConfiguration.java和MyApplication.java不应该包含任何hibernate包引用。然后你应该能够在任何需要的地方@Inject一个SessionFactory。