Hibernate中的buildSessionFactory()配置方法是否已被弃用?

223

当我将Hibernate版本从3.6.8更新到4.0.0时,我在下面这行代码中收到了一个有关废弃方法buildSessionFactory()的警告:

private static final SessionFactory sessionFactory =
         new Configuration().configure().buildSessionFactory();

根据Javadoc的建议,推荐使用另一种方法:buildSessionFactory(ServiceRegistry serviceRegistry)

但在文档中,我发现有一个已弃用的变体。


即使在4.3.8快速入门指南中,他们也使用了这个示例:new Configuration().configure().buildSessionFactory(); :( - Venkata Raju
@VenkataRaju 可能并不糟糕,因为在 Hibernate 5 中一切都回归正常,这个例子是正确的,但是 (!) 这里的所有配置示例都不适用于 Hibernate 5 - v.ladynev
18个回答

385

是的,它已被弃用。请使用以下内容替换您的SessionFactory:

Hibernate 4.0、4.1、4.2

private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;

public static SessionFactory createSessionFactory() {
    Configuration configuration = new Configuration();
    configuration.configure();
    ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(
            configuration.getProperties()). buildServiceRegistry();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    return sessionFactory;
}

更新:

Hibernate 4.3中,ServiceRegistryBuilder已被废弃。请改用以下方式。

serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
            configuration.getProperties()).build();

6
org.hibernate.service.ServiceRegistryBuilder也已经过时了! - Accollativo
12
是的,看起来ServiceRegistryBuilder本身已经被弃用了。根据文档,建议使用StandardServiceRegistryBuilder代替。因此,我猜调用应该是new StandardRegistryBuilder().applySettings(configuration.getProperties()).build(); - Simon B
我在Hibernate 4.3中找不到StandardRegistryBuilder,它可能被更改了吗? - Dejell
7
需要使用buildServiceRegistry()方法而不是build()方法,对吗?我找不到ServiceRegistry.build()方法。 - Herbert
47
似乎“休眠团队”的使命是废弃他们所创建的一切。 - 3urdoch
显示剩余6条评论

16

是的,这个方法已被弃用。 http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/cfg/Configuration.html#buildSessionFactory() 明确告诉你要使用你找到的另一个方法 (buildSessionFactory(ServiceRegistry serviceRegistry)) - 所以请使用它。

文档是从一个版本复制到另一个版本的,并且很可能尚未更新(他们不会每个版本都重写手册),所以请相信 Javadocs。

有关此更改的详细信息,请参见:

一些其他参考资料:


那么现在我们如何创建会话?分配给serviceRegistry接口的对象是什么? - Ismail Marmoush
@IsmailMarmoush - 我还没有太多时间去尝试,但我已经添加了一些额外的参考资料。 - ziesemer

8
或者
public class Hbutil {

    private static SessionFactory sessionFactory;
    private static ServiceRegistry serviceRegistry;

    private static SessionFactory configureSessionFactory() throws HibernateException {
        Configuration configuration = new Configuration();
        configuration.configure();
        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        return sessionFactory;
    }

    public static SessionFactory getSessionFactory() {
        return configureSessionFactory();

    }
}

这段代码中使用了一些已弃用的方法。 - Kevin Bowersox

6

代码已在Hibernate 4.3.0中验证过可以工作。请注意,您可以删除XML文件名参数,或者提供自己的路径。这与其他帖子类似(但更正了拼写错误),但是此代码正确。

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;    


Configuration configuration = new Configuration();
configuration.configure("/com/rtw/test/hiber/hibernate.cfg.xml");
ServiceRegistry  serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();        
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);

4
就是这样简单:JBoss文档并不完美地维护着。遵循JavaDoc所说的:buildSessionFactory(ServiceRegistry serviceRegistry)。请点击此处

4

在不同版本的文档中发现差异并不罕见。大多数开发人员认为文档编写是一件繁琐的事情,他们往往会拖延。

通常来说,如果javadoc说了一件事情,而其他非javadoc文档与之相反,那么javadoc更准确的可能性更大。程序员更有可能随着代码变化而更新javadoc,因为javadoc的“源”与代码在同一个文件中。

@deprecated标记的情况下,可以肯定的是,javadoc更准确。开发人员经过仔细考虑后才会弃用某些东西......(一般情况下)他们不会取消弃用。


1
除非它被称为System.getenv(String),否则它们不会取消弃用。http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4199068 - bestsss
1
很常见的是发现一些烂项目,懒惰的开发者不费心将文档与代码保持一致,这让用户感到非常困惑,他们试图通过在代码中寻找注释来理解它的工作原理,但除了 /** TODO: comment-me */ 之外什么也找不到。:-\ - zakmck
@bestsss ...或者它被称为Configuration.buildSessionFactory() ;) - v.ladynev

4
在最新版本的Hibernate 4.3.0及以后,创建SessionFactory对象的更好方式如下所示:
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().
applySettings(configuration.getProperties());
SessionFactory factory = configuration.buildSessionFactory(builder.build());

出现错误:Configuration 中的 buildSessionFactory() 方法对于参数 (StandardServiceRegistry) 不适用。 - Anju

3
如果您正在使用 Hibernate 5.2 或更高版本,则可以使用以下内容:
  private static StandardServiceRegistry registry;
  private static SessionFactory sessionFactory;

  public static SessionFactory getSessionFactory() {
    if (sessionFactory == null) {
      try {
        // Creating a registry
        registry = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();

        // Create the MetadataSources
        MetadataSources sources = new MetadataSources(registry);

        // Create the Metadata
        Metadata metadata = sources.getMetadataBuilder().build();

        // Create SessionFactory
        sessionFactory = metadata.getSessionFactoryBuilder().build();

      } catch (Exception e) {
        e.printStackTrace();
        if (registry != null) {
          StandardServiceRegistryBuilder.destroy(registry);
        }
      }
    }
    return sessionFactory;
  }

  //To shut down
 public static void shutdown() {
    if (registry != null) {
      StandardServiceRegistryBuilder.destroy(registry);
    }
  }

2

简述

是的,有更好的方法来引导Hibernate,比如以下方法。

本地引导Hibernate

传统的Configuration对象比使用自Hibernate 4版本以来引入的BootstrapServiceRegistryBuilder对象功能较弱:

final BootstrapServiceRegistryBuilder bsrb = new BootstrapServiceRegistryBuilder()
    .enableAutoClose();

Integrator integrator = integrator();
if (integrator != null) {
    bsrb.applyIntegrator( integrator );
}

final BootstrapServiceRegistry bsr = bsrb.build();

final StandardServiceRegistry serviceRegistry = 
    new StandardServiceRegistryBuilder(bsr)
        .applySettings(properties())
        .build();

final MetadataSources metadataSources = new MetadataSources(serviceRegistry);

for (Class annotatedClass : entities()) {
    metadataSources.addAnnotatedClass(annotatedClass);
}

String[] packages = packages();
if (packages != null) {
    for (String annotatedPackage : packages) {
        metadataSources.addPackage(annotatedPackage);
    }
}

String[] resources = resources();
if (resources != null) {
    for (String resource : resources) {
        metadataSources.addResource(resource);
    }
}

final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder()
    .enableNewIdentifierGeneratorSupport(true)
    .applyImplicitNamingStrategy(ImplicitNamingStrategyLegacyJpaImpl.INSTANCE);

final List<Type> additionalTypes = additionalTypes();
if (additionalTypes != null) {
    additionalTypes.stream().forEach(type -> {
        metadataBuilder.applyTypes((typeContributions, sr) -> {
            if(type instanceof BasicType) {
                typeContributions.contributeType((BasicType) type);
            } else if (type instanceof UserType ){
                typeContributions.contributeType((UserType) type);
            } else if (type instanceof CompositeUserType) {
                typeContributions.contributeType((CompositeUserType) type);
            }
        });
    });
}

additionalMetadata(metadataBuilder);

MetadataImplementor metadata = (MetadataImplementor) metadataBuilder.build();

final SessionFactoryBuilder sfb = metadata.getSessionFactoryBuilder();
Interceptor interceptor = interceptor();
if(interceptor != null) {
    sfb.applyInterceptor(interceptor);
}

SessionFactory sessionFactory = sfb.build();

JPA引导

您还可以使用JPA引导Hibernate:

PersistenceUnitInfo persistenceUnitInfo = persistenceUnitInfo(getClass().getSimpleName());
Map configuration = properties();

Interceptor interceptor = interceptor();
if (interceptor != null) {
    configuration.put(AvailableSettings.INTERCEPTOR, interceptor);
}

Integrator integrator = integrator();
if (integrator != null) {
    configuration.put(
        "hibernate.integrator_provider", 
        (IntegratorProvider) () -> Collections.singletonList(integrator));
}

EntityManagerFactoryBuilderImpl entityManagerFactoryBuilder = 
    new EntityManagerFactoryBuilderImpl(
        new PersistenceUnitInfoDescriptor(persistenceUnitInfo), 
        configuration
);
EntityManagerFactory entityManagerFactory = entityManagerFactoryBuilder.build();

这样做,您正在构建EntityManagerFactory而不是SessionFactory。但是,SessionFactory扩展了EntityManagerFactory,因此实际构建的对象也是SessionFactoryImpl

结论

这两种引导方法影响Hibernate的行为。使用本机引导时,Hibernate以JPA之前的传统模式运行。

使用JPA引导时,Hibernate将按照JPA规范运行。

这两种模式之间有几个差异:

有关这些差异的更多细节,请查看JpaCompliance类。

1
public class HibernateSessionFactory {

private static final SessionFactory sessionFactory = buildSessionFactory1();

private static SessionFactory buildSessionFactory1() {
Configuration configuration = new Configuration().configure(); // configuration
                                                                // settings
                                                                // from
                                                                // hibernate.cfg.xml

StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();


serviceRegistryBuilder.applySettings(configuration.getProperties());

ServiceRegistry serviceRegistry = serviceRegistryBuilder.build();

return configuration.buildSessionFactory(serviceRegistry);
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
 }

public static void shutdown() {
// Close caches and connection pools
getSessionFactory().close();
 }

'StandardServiceRegistryBuilder' 也已经被弃用。 - NixRam
@NitinRam StandardServiceRegistryBuilder 没有被弃用。 - JPG
Hibernate 中的弃用功能有时会让人感到很奇怪。曾经有一段时间它被标记为弃用。https://dev59.com/PHXYa4cB1Zd3GeqP1ACe - NixRam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接