Hibernate 数据库服务关闭时允许EntityManagerFactory注入为null
我有一个Jersey web服务,它使用Hibernate进行一些持久化。我使用hk2提供程序逻辑实现了EntityManagerFactory的创建/处理。我发现了堆栈溢出,这极大地帮助保持了较低的DB连接数。我不想强迫用户使用DB,所以我希望代码能够优雅地处理这种情况。然而,除了不得不注释我的@Inject注释外,我似乎无法理解它。有人知道如何使用自定义@Inject并将其编码为允许为null吗 当Persistence.create失败时,我试图在DBManager中捕获该异常,并在我的WebServiceClass中检查null。但是它在@Inject行崩溃,并且没有捕获异常。我查看了findOrCreate null异常,发现有一个名为SupportsAllCreation()的方法,但没有找到如何使用它的示例 这就是我的代码的样子: 使用HK2的可注入DB提供程序:Hibernate 数据库服务关闭时允许EntityManagerFactory注入为null,hibernate,jpa,dependency-injection,jersey,jax-rs,Hibernate,Jpa,Dependency Injection,Jersey,Jax Rs,我有一个Jersey web服务,它使用Hibernate进行一些持久化。我使用hk2提供程序逻辑实现了EntityManagerFactory的创建/处理。我发现了堆栈溢出,这极大地帮助保持了较低的DB连接数。我不想强迫用户使用DB,所以我希望代码能够优雅地处理这种情况。然而,除了不得不注释我的@Inject注释外,我似乎无法理解它。有人知道如何使用自定义@Inject并将其编码为允许为null吗 当Persistence.create失败时,我试图在DBManager中捕获该异常,并在我的W
public class DbManager
implements Factory<EntityManagerFactory>
{
private static EntityManagerFactory factory = null;
@Inject
public DbManager()
{
try
{
factory = Persistence.createEntityManagerFactory("myapp");
}
catch ( Exception eee )
{
// just means DB is not connected which I want to allow
System.out.println("No DB, that should be okay");
}
}
@Override
public EntityManagerFactory provide() {
return factory;
}
@Override
public void dispose(EntityManagerFactory emf) {
if ( emf != null && emf.isOpen() )
{
emf.close();
}
}
public EntityManagerFactory getEntityMgrFactory()
{
return factory;
}
}
然后是这样使用的:
@Singleton
@Path("myservice")
public class WebServiceClass
{
// NOTE: Right now I have to comment this to run without a DB
@Inject
private EntityManagerFactory entityManagerFactory = null;
...
// factory wrapper
public class EMFHolder {
private EntityManagerFactory emf;
public EMFHolder(EntityManagerFactory emf) { this.emf = emf;}
public EntityManagerFactory getEmf() { return this.emf;
}
// provider
public class DbManager implements Factory<EntityManagerFactory> {
// ...
@Override
public EMFHolder provide() {
return new EMFHolder(factory);
}
// ...
}
// using factory if not null
public class WebServiceClass
{
@Inject
private EMFHolder emfHolder;
public void doComethingWithEMF() {
if (emfHolder.getEmf() != null) {
// do something with the factory...
}
}
}
我得到的例外是
java.lang.IllegalStateException: Context
org.jvnet.hk2.internal.SingletonContext@6cae5847 findOrCreate returned a null for
descriptor SystemDescriptor(
implementation=com.db.DbManager
contracts={javax.persistence.EntityManagerFactory}
scope=javax.inject.Singleton
qualifiers={}
descriptorType=PROVIDE_METHOD
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@7050f2b1
proxiable=null
proxyForSameScope=null
analysisName=null
id=145
locatorId=0
identityHashCode=863132354
reified=true)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2075)
...
你可以看一看
使用该模式,如果不存在数据库,您可以在配置中注册
工厂的空对象
实现
,而不是DbManager
,您需要的是EMF依赖项的动态注入。通常,所有注入都是静态的,这意味着在创建依赖于注入的对象时,所有依赖项都是关联的
使用任何依赖项注入机制(不仅仅是HK2)的一个简单解决方案是创建一个包装器对象,该对象将保存对真实依赖项的引用,如果依赖项不可用,则为null。通过将EntityManagerFactory包装成一个或零个元素的集合,也可以实现同样的效果。它可能是这样的:
@Singleton
@Path("myservice")
public class WebServiceClass
{
// NOTE: Right now I have to comment this to run without a DB
@Inject
private EntityManagerFactory entityManagerFactory = null;
...
// factory wrapper
public class EMFHolder {
private EntityManagerFactory emf;
public EMFHolder(EntityManagerFactory emf) { this.emf = emf;}
public EntityManagerFactory getEmf() { return this.emf;
}
// provider
public class DbManager implements Factory<EntityManagerFactory> {
// ...
@Override
public EMFHolder provide() {
return new EMFHolder(factory);
}
// ...
}
// using factory if not null
public class WebServiceClass
{
@Inject
private EMFHolder emfHolder;
public void doComethingWithEMF() {
if (emfHolder.getEmf() != null) {
// do something with the factory...
}
}
}
//工厂包装器
公共类EMFHolder{
私人实体管理工厂emf;
公共EMFHolder(EntityManagerFactory emf){this.emf=emf;}
public EntityManagerFactory getEmf(){返回this.emf;
}
//提供者
公共类DbManager实现工厂{
// ...
@凌驾
公共EMFHolder提供(){
退回新的EMFHolder(工厂);
}
// ...
}
//如果不为空,则使用工厂
公共类WebServiceClass
{
@注入
私人电话机;
public void doComethingWithEMF(){
if(emfHolder.getEmf()!=null){
//对工厂做点什么。。。
}
}
}
也看看HK2,但我认为它不允许您从
provide
方法返回空值。因此,以您的示例为例,您是说如果EMF创建失败,您仍然希望它正常工作,这意味着注入将为空?这有什么好处?我理解正确吗uess问题是,如果没有db,用户将如何与服务交互?对端点的调用将返回什么?是的,我希望它在EMF创建失败时正常工作。对端点的调用将向用户返回一些数据,这些数据可能会保留,也可能不会保留,这取决于db是否已安装并正在运行。我可以使用更多详细信息。我创建NullableDbMgr时出错,但提供()方法应该为EntityManagerFactory返回null,对吗?如果是,它会导致相同的问题。你是说我应该提供一些不同的东西吗?如果是,这不会破坏提供程序的有效性吗?是的,你还应该创建EntityManagerFactory的null对象
实现,以便在没有这应该警告你,如果<代码> EntIdMaulePrimeStudio<代码>不是我自己的接口,为什么我直接在我的消费类?AppAt中使用它,为了解决你的情况,你也可以考虑使用内存数据库。空对象的想法是,你不会从No.>提供“< /Cord>”方法返回null,但是你将创建你自己的IMP。EntityManagerFactory
接口的实现,带有空方法(例如,可能引发运行时异常)。在客户端代码中,您将尝试检查是否接收到此类空对象。如果是,则表示没有与数据库的连接。否则,您将像往常一样使用注入的EMF对象。