Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 春季及;Hibernate SessionFactory-从停机的服务器恢复_Java_Hibernate_Spring_Orm - Fatal编程技术网

Java 春季及;Hibernate SessionFactory-从停机的服务器恢复

Java 春季及;Hibernate SessionFactory-从停机的服务器恢复,java,hibernate,spring,orm,Java,Hibernate,Spring,Orm,所以在spring之前,我们使用了HibernateUtil版本,如果成功建立了原始JDBC连接,它会缓存SessionFactory实例,否则会抛出SQLException。这使我们能够从由于身份验证或服务器连接问题而导致的SessionFactory的初始设置“错误”中恢复 我们转向Spring,并使用LocalSessionFactoryBean、C3P0数据源和各种注入了SessionFactory的dao类,以一种或多或少经典的方式连接东西 现在,如果在web应用程序运行时SQL se

所以在spring之前,我们使用了HibernateUtil版本,如果成功建立了原始JDBC连接,它会缓存SessionFactory实例,否则会抛出SQLException。这使我们能够从由于身份验证或服务器连接问题而导致的SessionFactory的初始设置“错误”中恢复

我们转向Spring,并使用LocalSessionFactoryBean、C3P0数据源和各种注入了SessionFactory的dao类,以一种或多或少经典的方式连接东西

现在,如果在web应用程序运行时SQL server似乎未启动,则web应用程序将永远无法恢复。对dao方法的所有访问都会中断,因为注入了null sessionfactory。(正确创建sessionfactory后,连接池主要处理sql server的启动/关闭状态,因此可以进行恢复)

现在,dao方法默认连接为单例,我们可以将它们更改为原型。但我认为这并不能解决问题——我相信LocalSessionFactoryBean现在已经“卡住”并缓存空引用(不过,我不得不承认,我还没有对此进行测试)。 这一定是一个关系到人们的问题

按以下建议尝试代理--此操作失败

首先,我不得不忽略调用
LocalSessionFactory.buildSessionFactory
——它不可见的建议(坦白地说,这在反编译中似乎是错误的)

相反,我尝试了如下修改版本:

覆盖新闻工厂。在末尾返回指向下面列出的调用处理程序的
SessionFactory
代理

这也失败了

org.hibernate.HibernateException:未找到用于配置的本地数据源-必须在LocalSessionFactoryBean上设置“DataSource”属性

现在,如果将
newSessionfactory()
更改为
return config.buildSessionFactory()
(而不是代理)它可以工作,但当然不再显示所需的代理行为

public static class HibernateInvocationHandler implements InvocationHandler {
    final private Configuration config;
    private SessionFactory realSessionFactory;
    public HibernateInvocationHandler(Configuration config) {
        this.config=config;
        }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if (false) proxy.hashCode();
        System.out.println("Proxy for SessionFactory called");
            synchronized(this) {
                if (this.realSessionFactory == null){
                    SessionFactory sf =null;
                    try {
                        System.out.println("Gonna BUILD one or die trying");

                        sf=this.config.buildSessionFactory();
                    } catch (RuntimeException e) {
                        System.out.println(ErrorHandle.exceptionToString(e));
                        log.error("SessionFactoryProxy",e);
                        closeSessionFactory(sf);
                        System.out.println("FAILED to build");
                        sf=null;
                    }
                    if (sf==null) throw new RetainConfigDataAccessException("SessionFactory not available");
                    this.realSessionFactory=sf;                     
                }
                return method.invoke(this.realSessionFactory, args);    
        }

    }
newSessionFactory中的代理创建如下所示

    SessionFactory sfProxy= (SessionFactory) Proxy.newProxyInstance(
            SessionFactory.class.getClassLoader(),
            new Class[] { SessionFactory.class },
            new HibernateInvocationHandler(config));
您可以返回这个代理(失败)或config.buildSessionFactory(),它可以工作,但不能解决最初的问题

bozho提出了另一种方法,使用getObject()。请注意d)中的致命缺陷,因为buildSessionFactory不可见

a) 如果this.sessionfactory为非null,则不需要代理,只需返回 b) 如果是,请构建一个代理,该代理。。。 c) 应该包含sessionfactory的私有引用,并且每次调用它时都检查它是否为null。如果是这样,则构建一个新工厂,如果成功,则分配给私有引用并从现在开始返回它。
d) 现在,说明如何从getObject()构建工厂。你的答案应该包括调用buildSessionFactory……但是你不能。一个人可以自己创建工厂,但你最终会冒着破坏spring的风险(看看buildSessionFactory代码)

你不应该担心这一点。在生产和开发过程中,启动应用程序是很少会做的事情——无论如何,您都需要DB服务器

如果数据库服务器在应用程序运行时停止,应用程序无法恢复,您应该担心

您可以做的是扩展
LocalSessionFactoryBean
并重写
getObject()
方法,并在sessionFactory为null的情况下使其返回代理(通过
java.lang.reflect.proxy
或/)。这样将注入一个
SessionFactory
。代理应该持有对裸
会话工厂的引用,该引用最初为空。每当请求代理连接时,如果
sessionFacotry
仍然为空,则调用
buildSessionFactory()
(属于
LocalSessionFactoryBean
)并委托给它。否则抛出异常。(然后当然映射您的新工厂bean,而不是当前工厂bean)


因此,即使数据库在启动时不可用,您的应用程序也将可用。但我自己不会为此烦恼。

你在启动时会得到堆栈跟踪吗?我得到了,如果你愿意,我可以发布它,但如果注入的会话工厂在dao中为空,这只不过是你所期望的……我已经找到了奇怪的数据源错误的原因。Spring非常故意地将引用置空(这是threadlocal)在buildSessionFactory中调用newSessionFactory之后。如果不重写classshow你的
getObject()
方法,你想不出解决这个问题的方法。getObject()没有条目,因为你不能使用你的方法。简单证明:如果this.sessionFactory为null,在不重写buildSessionFactory的情况下,如何从这里返回sessionFactory?嗯,我将研究该方法。我很欣赏这个建议,虽然我认为你的观点是错误的。目标受众是面向最终用户的,因此恢复非常重要。我同意,如果这是一个内部应用程序,或者是一个专业托管的应用程序,这不会是一个问题。你的代理建议似乎很有希望,但我无法让它发挥作用。从代理开始并不容易。您可能想问另一个问题,我相信代理正在工作,是LocalSessionFactory bean在与之抗争。你有什么特别的建议?@MJB通常不会对花了一些时间调查你的问题并给出你不理解的解决方案的人投反对票。