In my web app I use the session-per-request pattern. I have a connection pool and open sessions in a Filter using SessionFactory.openSession() and then Session.close().
In the same app, for a complex process, I want to use session-per-conversation. I tried to open a second Session with SessionFactory.openSession(), but subsequently calling Session.disconnect() does nothing.
How can I manually connect/disconnect sessions? This is my Hibernate configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost/.....</property>
<property name="hibernate.connection.username">...</property>
<property name="hibernate.connection.password">...</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.test_connection_on_checkout">true</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
</session-factory>
</hibernate-configuration>
The Java code:
longSession = mySessionFactory.openSession();
System.out.println(((SessionImplementor) longSession).isConnected());
longSession.disconnect();
System.out.println(((SessionImplementor) longSession).isConnected());
This outputs true twice...
I think this is related to this note in Hibernate Documents:
Note that disconnect() called on a session where the connection was
retrieved by Hibernate through its configured ConnectionProvider has
no effect, provided ConnectionReleaseMode.ON_CLOSE is not in effect
Also note to this in Documentation for session-per-conversation:
Committing a database transaction disconnects a session from the JDBC
connection and returns the connection to the pool
This say you need only to commit transactions to return the connection to the pool, except for the last transaction in your conversation:
// foo is an instance loaded earlier by the old session
Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start transaction
foo.setProperty("bar");
session.flush(); // Only for last transaction in conversation
t.commit(); // Also return JDBC connection
session.close(); // Only for last transaction in conversation
Related
Need some clarification and helps. Especially appreciate describing general concepts or link where they are described.
So, on the hibernate website I have read the next one:
For use inside an application server, you should almost always
configure Hibernate to obtain connections from an application server
javax.sql.Datasource registered in JNDI. You will need to set at least
one of the following properties:
And I have a few question because at the moment I am really confused about all of that stuff with DataSource, DataDriver, Tomcat and Hibernate in general.
Does configuring Datasource and binding SessionFactory to the JNDI
is the same process?
If no, for what we use DataSource and for why we need to bind SessionFactory to JNDI (in general)?
Am I understood right? If we configure DataSource in hibernate.cfg.xml file we don't need to configure it in {tomcat}/conf/server.xml or {tomcat}/conf/context.xml?
What is hibernate.jndi.url? Does it is the same as hibernate.connection.url?
What is hibernate.connection.datasource? In docs I read that it is "datasource JNDI name", so if I understood right it can be any name?
From Hibernate docs I read that setting at least one of the properties hibernate.connection.datasource, hibernate.jndi.url, hibernate.jndi.class, hibernate.connection.username, hibernate.connection.password makes my app use javax.sql.Datasource registered in JNDI. So does the next conf already configured to use DataSource?
How to check that DataSource used and configured fine?
My hibernate.cfg.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.use_sql_comments">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.generate_statistics">true</property>
<!--http://stackoverflow.com/questions/2067526/hibernate-connection-pool-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!--For use inside an application server, you should almost always configure Hibernate to obtain connections from an application server javax.sql.Datasource registered in JNDI. You will need to set at least one of the following properties:-->
<!--hibernate.connection.datasource,hibernate.jndi.url,hibernate.jndi.class,hibernate.connection.username,hibernate.connection.password-->
<!--Datasource config-->
<property name="hibernate.connection.datasource">jdbc:mysql://localhost/easywordweb</property>
<!--<property name="hibernate.jndi.url">??????? what is it</property>-->
<!--/Datasource config-->
<!--*****************************************************************-->
<!--C3P0 config-->
<!--Hibernate will obtain and pool connections using java.sql.DriverManager if you set the 5 following properties -->
<!--hibernate.connection.driver_class,hibernate.connection.url,hibernate.connection.username,hibernate.connection.password,hibernate.connection.pool_size-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/easywordweb</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">password</property>
<!--We can use a third party pool for best performance and stability, for example c3p0. Just replace the hibernate.connection.pool_size property with connection pool specific settings. This will turn off Hibernate's internal pool. For example, you might like to use c3p0. -->
<!--<property name="hibernate.connection.pool_size">140</property>-->
<property name="hibernate.c3p0.max_size">140</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.acquire_increment">5</property>
<!--max to cache-->
<property name="hibernate.c3p0.max_statements">50</property>
<!--The seconds a Connection can remain pooled but unused before being discarded. Zero means idle connections never expire. Hibernate default: 0-->
<property name="hibernate.c3p0.timeout">21600</property>
<!--for test, change futher-->
<property name="hibernate.c3p0.preferredTestQuery">SELECT 1;</property>
<!--at every connection checkin to verify that the connection is valid-->
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<!--at every connection checkout to verify that the connection is valid-->
<property name="hibernate.c3p0.testConnectionOnCheckin">true</property>
<!--/for test, change futher-->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!--/C3P0 config-->
<!--*****************************************************************-->
<property name="hibernate.c3p0.validate">true</property>
<!--c3p0 will test all idle, pooled but unchecked-out connections, every this number of seconds-->
<property name="hibernate.c3p0.idle_test_period">21000</property>
<property name="hibernate.jdbc.batch_size">20</property>
<!--Number rows to be returned if no setted-->
<property name="hibernate.jdbc.fetch_size">20</property>
<property name="hibernate.jdbc.use_get_generated_keys">true</property>
<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
<!--FIXING: Table "...".hibernate_sequence table not found.-->
<property name="hibernate.id.new_generator_mappings">false</property>
</session-factory>
</hibernate-configuration>
Thank's everyone in advance.
In the config you have posted you are initializing the connection pool within your application.
An alternative is to delegate the creation of the database pool to your app/web server and expose it as a JNDI resource. Your application need then only specify the name of the JNDI datasource to obtain a connection.
Doing this in Tomcat is documented here:
https://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html
Your hibernate.cfg.xml then looks like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.use_sql_comments">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.generate_statistics">true</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- The Server configured JNDI datasource -->
<property name="hibernate.connection.datasource">java:comp/env/jdbc/MyLocalDB</property>
<property name="hibernate.jdbc.batch_size">20</property>
<!--Number rows to be returned if no setted-->
<property name="hibernate.jdbc.fetch_size">20</property>
<property name="hibernate.jdbc.use_get_generated_keys">true</property>
<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
<!--FIXING: Table "...".hibernate_sequence table not found.-->
<property name="hibernate.id.new_generator_mappings">false</property>
</session-factory>
</hibernate-configuration>
I am new bee to Hibernate and trying out things.
One thing that seems to amuse all is how to connect to different databases?
I have two questions here:
If in the same web app I need to connect to MySQL and Oracle, how do I do it?
I am using MySQL and have two databases test1 and test2, how to connect and retrieve data?
I have read in a blog that we can create different configuration files and do it.
I tried it but was not sucessful.
Here's what I tried:
SessionFactory sf = (SessionFactory) new Configuration().configure(path);
Where path is the path of the config file.
Is this the right way?
Using annotation mappings as an example:
Configuration cfg1 = new AnnotationConfiguration();
cfg1.configure("/hibernate-oracle.cfg.xml");
cfg1.addAnnotatedClass(SomeClass.class); // mapped classes
cfg1.addAnnotatedClass(SomeOtherClass.class);
SessionFactory sf1 = cfg1.buildSessionFactory();
Configuration cfg2 = new AnnotationConfiguration();
cfg2.configure("/hibernate-mysql.cfg.xml");
cfg2.addAnnotatedClass(SomeClass.class); // could be the same or different than above
cfg2.addAnnotatedClass(SomeOtherClass.class);
SessionFactory sf2 = cfg2.buildSessionFactory();
Then use sf1 and sf2 to get the sessions for each database. For mapping files, you just use cfg.addClass instead of addAnnotatedClass. Put the cfg.xml files in the root package in this case. Those will have the Oracle or MySQL dialect and connection information.
It cannot be done using one hibernate configuration file. You need to have two configurations files for it.
To configure mysql database
hibernate-mysql.cfg.xml
To configure oracle database
hibernate-oracle.cfg.xml
In Details, mysql configuration file be like this.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">PASSWORD</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/UR_DB_NAME</property>
<property name="hibernate.connection.username">USERNAME</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<mapping class="domain.EmployeeMysql"></mapping>
</session-factory>
</hibernate-configuration>
In Details, oracle configuration file be like this.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.password">PASSWORD</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:UR DB NAME</property>
<property name="hibernate.connection.username">USERNAME</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="show_sql">true</property>
<mapping class="domain.EmployeeOracleSql"></mapping>
</session-factory>
</hibernate-configuration>
And code should be like this.
mysql configuration
private static SessionFactory sessionAnnotationFactory;
sessionAnnotationFactory = new Configuration().configure("hibernate-mysql.cfg.xml").buildSessionFactory();
Session session = sessionAnnotationFactory.openSession();
oracle sql configuration
sessionAnnotationFactory = new Configuration().configure("hibernate-oracle.cfg.xml").buildSessionFactory();
Session session = sessionAnnotationFactory.openSession()
Ideally you should move to Distributed transaction type of system[using Java Transaction Analyzer org.hibernate.transaction.JTATransactionFactory] in this case. If you are running in JBoss App Server, you can do it by using "Distributed Transaction Managers". You can learn more about it here.
You can also use a catalog with the value of the other database
#Table(name = "foo", schema = "bar", catalog = "OtherDatabase")
You can also Add mapping class in configuration.xml file
Note : this is for annotations and for resources use resources keyword instead of class
<mapping class="packageName.classNmae1"/>
<mapping class="packageName.classNmae2"/>
You can connect two databases test1 and test2, retrieve data with only one hibernate with some tricks:
hibernate SQLQuery: just add database name with the table "select * from test1.table1", "select * from test2.table2"
hibernate persistence: using the key schema in the hibernate mapping xml
<class name="Table1Class" table="table1" schema="test1">
<class name="Table2Class" table="table2" schema="test2">
i am trying Hibernate 4 in Netbeans 8, the problem is that after the the committed is done the application still running.
Here is the code
public class TestHibernateAnotation {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Users user = new Users();
Users user2 = new Users();
user2.setUser_name("Djalil");
user.setUser_name("Daniel");
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
session.save(user);
session.save(user2);
session.getTransaction().commit();
session.close();
System.out.print("End of code");
}
}
My Hibernate Config
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate- configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/SalesTest</property>
<property name="hibernate.connection.username">postgres</property>
<property name="hibernate.connection.password">admin</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<mapping class="testhibernateanotation.NewClass"/>
<mapping class="testhibernateanotation.Users"/>
any Idea about this issue
thank you,
You need to explicitly destroy the service registry after session.close();. This seems to be a bug in newer hibernate versions. So basically your code that cleans up at the end should look like :
sessionFactory.close();
StandardServiceRegistryBuilder.destroy(sessionFactory.getSessionFactoryOptions().getServiceRegistry());
Plug: I had posted an example here - including this issue.
I found the solution (in an other post),
it would be adding this to your config files:
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">100</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.max_statements">10</property>
<property name="hibernate.c3p0.min_size">10</property>
<property name="hibernate.c3p0.timeout">100</property>
They said that it is bug in hibernate 4
you will have to close the SessionFactory object [ HibernateUtil.getSessionFactory().openSession() ]
The SessionFactory is a heavyweight object; it is usually created during application start up and kept for later use.The SessionFactory is a thread safe object and used by all the threads of an application.
We can create one SessionFactory implementation per database in any application. If your application is referring to multiple databases, then you need to create one SessionFactory per database.
its how hibernate SessionFactory was designed.
https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/SessionFactory.html
I use JBOSS 7.1 web server for my application. I configured JBOSS connection pool and use it for JDBC connections. I also use hibernate in my application. And i want to know if hibernate also use this connection pool or me need to configure other connection pool(for example c3p0) for hibernate?
C3P0 Connection Pool
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
hibernate.c3p0.min_size:
Minimum number of JDBC connections in the pool.
Hibernate default: 1
hibernate.c3p0.max_size:
Maximum number of JDBC connections in the pool.
Hibernate default: 100
hibernate.c3p0.timeout:
When an idle connection is removed from the pool (in second).
Hibernate default: 0, never expire.
hibernate.c3p0.max_statements:
Number of prepared statements will be cached. Increase performance.
Hibernate default: 0, caching is disable.
hibernate.c3p0.idle_test_period:
idle time in seconds before a connection is automatically validated.
Hibernate default: 0
http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch01.html
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#localhost:1521:schema</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.default_schema">schema</property>
<property name="show_sql">true</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
hibernate.c3p0.min_size – Minimum number of JDBC connections in the pool. Hibernate default: 1
hibernate.c3p0.max_size – Maximum number of JDBC connections in the pool. Hibernate default: 100
hibernate.c3p0.timeout – When an idle connection is removed from the pool (in second). Hibernate default: 0, never expire.
hibernate.c3p0.max_statements – Number of prepared statements will be cached. Increase performance. Hibernate default: 0 , caching is disable.
hibernate.c3p0.idle_test_period – idle time in seconds before a connection is automatically validated. Hibernate default: 0
more detail refer link
I'm fairly new at this and I'm stuck. If someone could help, that would be great.
My code right now uses inbuilt connection pool, how to change to Weblogic configured connection pool ? My code right now is as below:
hibernate-cfg.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<property name="hibernate.connection.release_mode">after_transaction</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!-- Configure BLOB/CLOB settings in hibernate -->
<property name="hibernate.connection.SetBigStringTryClob">true</property>
<property name="hibernate.jdbc.batch_size">0</property>
<!--Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="cache.use_query_cache">false</property>
<property name="cache.use_minimal_puts">false</property>
<property name="max_fetch_depth">3</property>
<!-- Bind the getCurrentSession() method to the thread. -->
<property name="current_session_context_class">thread</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
</session-factory>
</hibernate-configuration>
Hibernate Session Class that has the getSession method:
public class HibernateSession {
public Session getSession() {
Configuration configuration = new AnnotationConfiguration();
configuration.setProperty("hibernate.connection.username", USERNAME);
configuration.setProperty("hibernate.connection.password", PASSWORD);
configuration.setProperty("hibernate.connection.url", DB_URL);
configuration.configure("hibernate.cfg.xml");
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
return session;
}
}
Hibernate version: 4.2.11.Final
Weblogic: 10.3.6
You need to use JNDI lookup to look up the datasource you configured via WebLogic Admin console.