Hibernate 5 :- org.hibernate.MappingException: Unknown entity - java

I am getting the error message org.hibernate.MappingException: Unknown entity when i am trying to integrate hibernate 5.0 with mysql
This seems to be an issue with hibernate5.0.0 and 5.0.1 . This works fine with hibernate 4.3.9
Maven dependices
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.0.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
hibernate.cfg.xml
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3307/SampleDB
</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping class="UserA.User"></mapping>
</session-factory>
HibernateMain.java code
package UserA;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.mapping.Map;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.service.ServiceRegistry;
public class HibernateMain {
public static void main(String[] args) {
Configuration configuration = new Configuration();
configuration.configure();
ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
SessionFactory sf = configuration.buildSessionFactory(sr);
User user1 = new User();
user1.setUserName("Arpit");
user1.setUserMessage("Hello world from arpit");
user1.setUserId(22);
Session ss = sf.openSession();
ss.beginTransaction();
// saving objects to session
ss.save(user1);
ss.getTransaction().commit();
ss.close();
}
}
User.java
package UserA;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity(name="User_table")
public class User {
#Id
int userId;
#Column(name = "User_Name")
String userName;
#Column(name = "User_Message")
String userMessage;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserMessage() {
return userMessage;
}
public void setUserMessage(String userMessage) {
this.userMessage = userMessage;
}
}

I have fixed the same issue with Hibernate 5. There is a problem in this code
Configuration configuration = new Configuration();
configuration.configure();
ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
SessionFactory sf = configuration.buildSessionFactory(sr);
This code works fine for Hibernate 4.3.5, but the same code has the same issue for Hibernate 5.
When you do configuration.buildSessionFactory(sr), using Hibernate 5, Configuration losts all information about mapping that gets by call configuration.configure().
Solution
To fix the issue, if you use standard configuration files hibernate.cfg.xml and hibernate.properties, you can create the session factory by this way (without ServiceRegistry)
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Loading properties
If you have properties in a file other then hibernate.properties, you can build session factory using StandardServiceRegistryBuilder (anyway, if you have hibernate.properties and other file, it will be loaded both)
To load properties as a resource
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().
configure().loadProperties("hibernate-h2.properties").build();
SessionFactory sf = new Configuration().buildSessionFactory(serviceRegistry);
You need to have hibernate-h2.properties in the class path (root of the sources folder, resources folder). You can specify a path from the root source folder too
/com/github/xxx/model/hibernate-h2.properties.
To load properties from a path in the file system
File propertiesPath = new File("some_path");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().
configure().loadProperties(propertiesPath).build();
SessionFactory sf = new Configuration().buildSessionFactory(serviceRegistry);
You can find an example console application using this approach here fluent-hibernate-mysql. It uses a utility class to build the session factory from the fluent-hibernate library.
Incorrect Hibernate 5 tutorial
There is an incorrect example in Hibernate 5 tutorial 1.1.6. Startup and helpers. It uses this code
return new Configuration().configure().buildSessionFactory(
new StandardServiceRegistryBuilder().build() );
It doesn't do a proper configuration.

In Hibernate 5, you need to build StandardServiceRegistry and Metadata to build SessionFactory. You could use the following HibernateUtil to build SessionFactory. hibernate.cfg.xml should be in the root of the classpath of your application.
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder() .configure("hibernate.cfg.xml").build();
Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().build();
return metadata.getSessionFactoryBuilder().build();
}
catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Also, If you're using Hibernate 5 and using #Id as your identifier generation strategy then using GenerationType.AUTO will pick up the "sequence" identity generator by default with MySQL, which will give you an the com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'SampleDB.hibernate_sequence' doesn't exist exception, if you don't have it configured in your entities at identifier attributes. So with Hibernate 5, use GenerationType.IDENTITY instead.

You didn't add a configuration file
configuration.configure("/hibernate.cfg.xml");

Please make sure that you have created mapping file User.hbm.xml or User.xml file and included that file in hibernate.cfg.xml

Using this:
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
Session session = sessionFactory.openSession();
instead of this:
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
solved the issue with Hibernate 5.2.10.Final.

I was facing the same issue & I searched for almost 2 hours and tried with different possible ways like replacing old hibernate jars&changing the db table schema. But finally got the solution as below;
//This line to be replaced with below commented line
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Replace above for
Configuration config = new Configuration().configure();
ServiceRegistry servReg = new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build();
SessionFactory factory = config.buildSessionFactory(servReg);
It will then work fine..

Related

How to run standalone Hibernate 4 SchemaExport with Java Spring config

We have a Java Spring project using JPA with Hibernate 4 for ORM. We exclusively use Java config, so we don't have any hibernate.properties or persistence.xml mapping files.
We're also using Spring's Jsr310JpaConverters and some custom attribute converters implementing javax.persistence.AttributeConverter. The custom converters are picked up automatically by the package scan.
Other than that, our setup is fairly standard, basically just
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackageClasses = BasePackageMarker.class, repositoryBaseClass = InternalRepositoryImpl.class)
public class JpaConfig {
// values loaded from property file
public Properties jpaProperties() {
Properties jpaProperties = new Properties();
jpaProperties.setProperty(Environment.DIALECT, dialect);
jpaProperties.setProperty(Environment.HBM2DDL_AUTO, getHbm2ddlAuto());
// ...
return jpaProperties;
}
#Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName(driver);
config.setJdbcUrl(url);
config.setUsername(username);
config.setPassword(password);
// ...
return new HikariDataSource(config);
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setPackagesToScan(
BasePackageMarker.class.getPackage().getName(),
Jsr310JpaConverters.class.getPackage().getName()
);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setJpaProperties(jpaProperties());
return entityManagerFactoryBean;
}
// ...
}
I'm looking for a way to run Hibernate's SchemaExport to create our database schema, without running Tomcat or the Spring application, with the same configuration as starting the application with hbm2ddl=create, specifically finding all entity classes and attribute converters. I'd like to run it with Maven, but I can figure that part out once I know where to start.
I've found many outdated answers and libraries for Hibernate 3 or for XML config, nothing seems to work for our setup. I'm sure the answer is already out there, but at this point I'm quite confused and don't know what to try. Any solutions or pointers?
I think what you need go with AnnotationConfiguration():
In hibernate, database connection can also be achieved without using hibernate.cfg.xml. In hibernate annotation, there is a class named as AnnotationConfiguration. AnnotationConfiguration provides the method to configure database properties.
There are different methods of AnnotationConfiguration like .addAnnotatedClass, .addProperties etc. There is .configure() methods which seeks hibernate.cfg, We need not to use .configure() if we are not intended to use hibernate.cfg.
suppose I have entity User
package com.persistence;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue
private int id;
#Column(name="name")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
HibernateUtil class
public class HibernateUtil {
private static final SessionFactory concreteSessionFactory;
static {
try {
Properties prop= new Properties();
prop.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");
prop.setProperty("hibernate.connection.username", "root");
prop.setProperty("hibernate.connection.password", "");
prop.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
prop.setProperty("hbm2ddl.auto", "create");
concreteSessionFactory = new AnnotationConfiguration()
.addPackage("com.persistence")
.addProperties(prop)
.addAnnotatedClass(User.class)
.buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session getSession()
throws HibernateException {
return concreteSessionFactory.openSession();
}
public static void main(String... args){
Session session=getSession();
session.beginTransaction();
User user=(User)session.get(User.class, new Integer(1));
System.out.println(user.getName());
session.close();
}
}
Here's my solution based on Bhushan Uniyal's answer. Using reflection to find our entities and attribute converters.
public static void main(String... args) {
Properties prop = new Properties();
prop.setProperty("hibernate.connection.url", "jdbc:mysql://127.0.0.1:3306/db");
prop.setProperty("hibernate.connection.username", "user");
prop.setProperty("hibernate.connection.password", "xxxx");
prop.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
prop.setProperty("hibernate.hbm2ddl.auto", "create");
Configuration cfg = new Configuration()
.addPackage("com.persistence")
.addProperties(prop);
Reflections basePackageReflections = new Reflections(BasePackageMarker.class.getPackage().getName());
for (Class<?> entityClass : basePackageReflections.getTypesAnnotatedWith(Entity.class)) {
System.out.println("Adding entity class: " + entityClass.getSimpleName());
cfg.addAnnotatedClass(entityClass);
}
for (Class<? extends AttributeConverter> attributeConverter : basePackageReflections.getSubTypesOf(AttributeConverter.class)) {
System.out.println("Adding attribute converter: " + attributeConverter.getSimpleName());
cfg.addAttributeConverter(attributeConverter);
}
cfg.addAttributeConverter(Jsr310JpaConverters.LocalDateConverter.class);
cfg.addAttributeConverter(Jsr310JpaConverters.LocalDateTimeConverter.class);
cfg.addAttributeConverter(Jsr310JpaConverters.LocalTimeConverter.class);
cfg.addAttributeConverter(Jsr310JpaConverters.InstantConverter.class);
new SchemaExport(cfg).create(true, true);
}

Hibernate, nested transactions not supported

I have a trouble when running my web application that tries to get all the information from the table snowboard and put it in a list which I will then print out in the xHtml. But I get this exception down below.
org.hibernate.TransactionException: nested transactions not supported
The thing is that I have no clue why this exception happens so would appreciate some explanation. Also if you find any trouble in the code that would be fantastic.
This is the exception that I get.
HibernateUtil
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from standard (hibernate.cfg.xml)
// config file.
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
SnowHelper, HelperClass
public class SnowHelper {
Session session = null;
public SnowHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
public List getSnowboards() {
List<Snowboard> snowboardList = null;
try {
Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Snowboard");
snowboardList = (List<Snowboard>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return snowboardList;
}
}
HibernateCfg
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://cpsrv01.misshosting.com:3306/etvffqgz_snowshop</property>
<property name="hibernate.connection.username">etvffqgz_user</property>
<property name="hibernate.connection.password">759486456</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
<mapping resource="Hibernate/Account.hbm.xml"/>
<mapping resource="Hibernate/Snowboard.hbm.xml"/>
</session-factory>
</hibernate-configuration>
SnowboardBean, ManagedBean class
#Named(value = "snowboardBean")
#Dependent
public class SnowboardBean {
private List<Snowboard> snowList;
private SnowHelper snow;
/**
* Creates a new instance of SnowboardBean
*/
public SnowboardBean() {
snowList = new ArrayList<>();
snow = new SnowHelper();
snowList = snow.getSnowboards();
}
/**
* #return the snowList
*/
public List<Snowboard> getSnowList() {
return snowList;
}
}
In this bit here.. commit your transaction
Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Snowboard");
snowboardList = (List<Snowboard>) q.list();
tx.commit();
Otherwise you simply open a new transaction without closing it every time you invoke this method.. eventually one of them is opened while some other is not commited yet.
If you were using 'container managed transactions' (provided by Spring of EJB's) you would not have to worry about explicitly committing your transactions. Here you are using 'extended transaction management' and you have to take care of that yourself.

Hibernate package scan in JavaConfig

I'm trying to configure Spring and Hibernate without xml. Here's my SessionFactory bean. When I add annotated class to configuration - it works properly. I want to do it automatically, but adding a package to configuration doesnt helps for some reason, I get "Identificator is not mapped" error
#Bean
public SessionFactory sessionFactory(){
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.connection.driver_class",ds_driver);
hibernateProperties.put("hibernate.connection.url",ds_url);
hibernateProperties.put("hibernate.connection.username",ds_username);
hibernateProperties.put("hibernate.connection.password",ds_password);
hibernateProperties.put("hibernate.show_sql", false);
hibernateProperties.put("connection.pool_size", 1);
hibernateProperties.put("current_session_context_class", "thread");
hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration();
configuration.addPackage("app.entity"); // **doesnt work**
configuration.addAnnotatedClass(Identificator.class); // **works fine**
configuration.addProperties(hibernateProperties);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
The #addPackage() method reads the package-level metadata, and not the classes in the package. Unfortunately the Configuration class does not provide methods the achive what you want, you have to pass all classes to #addAnnotatedClass().
A possible (but not sure if recommendable) solution would be using another solution to find the required class descriptors, build a list from them, and then pass them in a loop to #addAnnotatedClass(). I am quite sure, that Spring has solutions for this.
public SessionFactory getSessionFactory() {
if (sessionFactory == null) {
Configuration configuration = new Configuration()
.configure(getMappedValue("Universal", "qb_hibernate"))
.setProperty("hibernate.connection.autocommit", "true")
.setProperty("connection.pool_size", "20000")
.setProperty("hibernate.dialect", getMappedValue("Universal", "dialect"))
.setProperty("hibernate.connection.driver_class", getMappedValue("Universal", "driver_class"))
.setProperty("hibernate.connection.url", getMappedValue("Universal", "url"))
.setProperty("hibernate.connection.username", getMappedValue("Universal", "userName"))
.setProperty("hibernate.connection.password", getMappedValue("Universal", "password"))
.setProperty("hibernate.show_sql", "false")
.setProperty("hibernate.current_session_context_class", "thread")
.setProperty("hibernate.query.factory_class", "org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory");
ServiceRegistry serviceRegistry
= new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
LocalSessionFactoryBuilder builder
= new LocalSessionFactoryBuilder(dataSource());
builder.scanPackages("zw.co.techno.xxxxx.model").buildSettings(serviceRegistry);
// builds a session factory from the service registry
// sessionFactory = configuration.buildSessionFactory(serviceRegistry);
sessionFactory = builder.buildSessionFactory();
}
return sessionFactory;
}

How can I fix JndiException on hibernate?

public class HibernateUtil {
private static SessionFactory sessionFactory = createSessionFactory();
private static ServiceRegistry serviceRegistry;
public static SessionFactory createSessionFactory() {
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
This is the class I have found on this forum to provide the session factory
but I keep getting the JndiException: Error parsing JNDI name []
16:07:57,659 WARN SessionFactoryObjectFactory:98 - Could not bind factory to JNDI
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:640)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:243)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:280)
at javax.naming.InitialContext.getNameParser(InitialContext.java:429)
at org.hibernate.util.NamingHelper.bind(NamingHelper.java:52)
at org.hibernate.impl.SessionFactoryObjectFactory.addInstance(SessionFactoryObjectFactory.java:90)
at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:293)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1145)
at util.HibernateUtil.(HibernateUtil.java:13)
The HibernateUtil is not the problem. You should look into your configuration file .cfg.xml and remove the name on the session-factory tag.
<session-factory name="">
to:
<session-factory>
This is a quick fix for that problem. The name attribute is only required to bind SessionFactory to JNDI.

Is the buildSessionFactory() Configuration method deprecated in Hibernate?

When I updated the Hibernate version from 3.6.8 to 4.0.0, I got a warning about deprecated method buildSessionFactory() in this line:
private static final SessionFactory sessionFactory =
new Configuration().configure().buildSessionFactory();
the Javadoc recommends using another method
buildSessionFactory(ServiceRegistry serviceRegistry)
but in the documentation I found deprecated variant
Yes it is deprecated. Replace your SessionFactory with the following:
In 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;
}
UPDATE:
In Hibernate 4.3 ServiceRegistryBuilder is deprecated. Use the following instead.
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
Yes, it is deprecated. http://docs.jboss.org/hibernate/core/4.0/javadocs/org/hibernate/cfg/Configuration.html#buildSessionFactory() specifically tells you to use the other method you found instead (buildSessionFactory(ServiceRegistry serviceRegistry)) - so use it.
The documentation is copied over from release to release, and likely just hasn't been updated yet (they don't rewrite the manual with every release) - so trust the Javadocs.
The specifics of this change can be viewed at:
Source code: https://github.com/hibernate/hibernate-core/commit/0b10334e403cf2b11ee60725cc5619eaafecc00b
Ticket: https://hibernate.onjira.com/browse/HHH-5991
Some additional references:
http://relation.to/Bloggers/HibernateCore40IsFinal
http://relation.to/19942.lace
http://docs.jboss.org/hibernate/core/4.0/devguide/en-US/html/ch07.html#services-registry
http://sourceforge.net/apps/mediawiki/hibernate/index.php?title=Category:Services
or
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();
}
}
Code verified to work in Hibernate 4.3.0. Notice you can remove the XML filename parameter, or else provide your own path there. This is similar to (but typos corrected) other posts here, but this one is correct.
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);
It's as simple as this: the JBoss docs are not 100% perfectly well-maintained. Go with what the JavaDoc says: buildSessionFactory(ServiceRegistry serviceRegistry).
A better way to create SessionFactory object in Latest hibernate release 4.3.0 onward is as follow:
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().
applySettings(configuration.getProperties());
SessionFactory factory = configuration.buildSessionFactory(builder.build());
It is not unusual to find discrepancies between different versions of documentation. Most developers view documentation as a chore, and they tend to put it off.
As a rule of thumb, if the javadoc says one thing and some non-javadoc documentation contradicts it, the chances are that the javadoc is more accurate. Programmers are more likely to keep the javadoc up to date with changes to the code ... because the "source" for the javadoc is in the same file as the code.
In the case of #deprecated tags, it is a virtual certainty that the javadoc is more accurate. Developers deprecate things after careful consideration ... and (generally speaking) they don't undeprecate them.
If you are using Hibernate 5.2 and above then you can use this:
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);
}
}
TL;DR
Yes, it is. There are better ways to bootstrap Hibernate, like the following ones.
Hibernate-native bootstrap
The legacy Configuration object is less powerful than using the BootstrapServiceRegistryBuilder, introduced since Hibernate 4:
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 bootstrap
You can also bootstrap Hibernate using JPA:
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();
This way, you are building the EntityManagerFactory instead of a SessionFactory. However, the SessionFactory extends the EntityManagerFactory, so the actual object that's built is aSessionFactoryImpl` too.
Conclusion
These two bootstrapping methods affect Hibernate behavior. When using the native bootstrap, Hibernate behaves in the legacy mode, which predates JPA.
When bootstrapping using JPA, Hibernate will behave according to the JPA specification.
There are several differences between these two modes:
How the AUTO flush mode works in regards to native SQL queries
How the entity Proxy is built. Traditionally, Hibernate did not hit the DB when building a Proxy, but JPA requires throwing an EntityNotFoundException, therefore demanding a DB check.
whether you can delete a non-managed entity
For more details about these differences, check out the JpaCompliance class.
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();
}
If anyone here after updating to 5.1 this is how it works
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
MetadataSources sources = new MetadataSources(registry);
Metadata metadata = sources.getMetadataBuilder().build();
sessionFactory = metadata.getSessionFactoryBuilder().build();
instead of the below in hibernate 4.3
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(
configuration.getProperties()). buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
public void sampleConnection() throws Exception {
Configuration cfg = new Configuration().addResource("hibernate.cfg.xml").configure();
StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
SessionFactory sessionFactory = configuration.buildSessionFactory(ssrb.build());
Session session = sessionFactory.openSession();
logger.debug(" connection with the database created successfuly.");
}
I edited the method created by batbaatar above so it accepts the Configuration object as a parameter:
public static SessionFactory createSessionFactory(Configuration configuration) {
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
factory = configuration.buildSessionFactory(serviceRegistry);
return factory;
}
In the main class I did:
private static SessionFactory factory;
private static Configuration configuration
...
configuration = new Configuration();
configuration.configure().addAnnotatedClass(Employee.class);
// Other configurations, then
factory = createSessionFactory(configuration);
In Hibernate 4.2.2
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class Test {
public static void main(String[] args) throws Exception
{
Configuration configuration = new Configuration()
.configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(
configuration.getProperties()).buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Users users = new Users();
... ...
session.save(users);
transaction.commit();
session.close();
sessionFactory.close();
}
}
Tested on 4.2.7 release
package com.national.software.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import com.national.software.dto.UserDetails;
public class HibernateTest {
static SessionFactory sessionFactory;
public static void main(String[] args) {
// TODO Auto-generated method stub
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("user1");
Configuration config = new Configuration();
config.configure();
ServiceRegistry serviceRegistry = (ServiceRegistry) new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
sessionFactory = config.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}
}
here are many APIs deprecated in the hibernate core framework.
we have created the session factory as below:
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
The method buildSessionFactory is deprecated from the hibernate 4 release and it is replaced with the new API. If you are using the hibernate 4.3.0 and above, your code has to be:
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
SessionFactory factory = configuration.buildSessionFactory(builder.build());
Class ServiceRegistryBuilder is replaced by StandardServiceRegistryBuilder from 4.3.0. It looks like there will be lot of changes in the 5.0 release. Still there is not much clarity on the deprecated APIs and the suitable alternatives to use. Every incremental release comes up with more deprecated API, they are in way of fine tuning the core framework for the release 5.0.
In hibernate 5.3.1, you can try this:
ServiceRegistry standardRegistry =
new StandardServiceRegistryBuilder().configure().build();
Metadata sources = new MetadataSources(standardRegistry).addAnnotatedClass(MyEntity.class).getMetadataBuilder().build();
SessionFactory sf = sources.buildSessionFactory();
Just import following package,
import org.hibernate.cfg.Configuration;

Categories