I am quite new in Spring world and I have developed a simple project that use Spring 3.2.1 and Hibernate 4.1.9 to implement a DAO. The project work correctly but I have some doubts about the use of #Transactional Spring annotation on CRUD method of this DAO.
This is the entire code of the class that implement the CRUD operation of my project:
package org.andrea.myexample.HibernateOnSpring.dao;
import java.util.List;
import org.andrea.myexample.HibernateOnSpring.entity.Person;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.springframework.transaction.annotation.Transactional;
public class PersonDAOImpl implements PersonDAO {
// Factory per la creazione delle sessioni di Hibernate:
private static SessionFactory sessionFactory;
// Metodo Setter per l'iniezione della dipendenza della SessionFactory:
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/** CREATE CRUD Operation:
* Aggiunge un nuovo record rappresentato nella tabella rappresentato
* da un oggetto Person
*/
#Transactional(readOnly = false)
public Integer addPerson(Person p) {
System.out.println("Inside addPerson()");
Session session = sessionFactory.openSession();
Transaction tx = null;
Integer personID = null;
try {
tx = session.beginTransaction();
personID = (Integer) session.save(p);
tx.commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return personID;
}
// READ CRUD Operation (legge un singolo record avente uno specifico id):
public Person getById(int id) {
System.out.println("Inside getById()");
Session session = sessionFactory.openSession();
Transaction tx = null;
Person retrievedPerson = null;
try {
tx = session.beginTransaction();
retrievedPerson = (Person) session.get(Person.class, id);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return retrievedPerson;
}
// READ CRUD Operation (recupera la lista di tutti i record nella tabella):
#SuppressWarnings("unchecked")
public List<Person> getPersonsList() {
System.out.println("Inside getPersonsList()");
Session session = sessionFactory.openSession();
Transaction tx = null;
List<Person> personList = null;
try {
tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Person.class);
personList = criteria.list();
System.out.println("personList: " + personList);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return personList;
}
// DELETE CRUD Operation (elimina un singolo record avente uno specifico id):
public void delete(int id) {
System.out.println("Inside delete()");
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Person personToDelete = getById(id);
session.delete(personToDelete);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
#Transactional
public void update(Person personToUpdate) {
System.out.println("Inside update()");
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
System.out.println("Insite update() method try");
tx = session.beginTransaction();
session.update(personToUpdate);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
Ok,as you can see some methods are annoted using #Transactional annotation.
I am readin the official documentation here http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html about the use of this annotation on methods and it see that: A method annoted using #Transactional must have transactional semantics but what it means with transactional semantics?
It means that the methos execution has to be considered as the execution of a transaction? So it means that the method operations have to be considered as a single operation that which may lead to a success or a failure, if successful, the results of operations has to be permanent, whereas in case of failure to return to the state prior to the start of the transaction.
Is this the meaning of use #Transactional annotation on a method?
And what exactly mean the readOnly = false attribute in the #Transactional annotation of the addPerson() method? it mean that I can also write a record in the database (and not only read it) or what? The doubt is related because I have understand that, by default, a transaction definied using #Transactional annotaion is read/write and not just read...
I have also try to delete the (readOnly = false) attribute and still work well (insert the new record in the database table)
The following dout is: "why some method are annoted using #Transactional annotation and some other methods not? is it a good pratcice to annote ALL CRUD method withd #Transactional?"
Tnx
Andrea
First of all, you shouldn't make DAO methods transactional, but service methods.
Second, using Transactional is a way to let Spring start and commit/rollback transactions for you. So you shouldn't start and commit transactions yourself.
Third: this will only work if you use a transaction manager that knows how to associate a Hibernate session with the transaction (typically, a HibernateTransactionManager). The session factory should also be handled by Spring, and injected by Spring in your DAOs. The code of the DAO should look like this:
Fourth: you should not open a new session, but get the current one, associated to the current transaction by Spring.
public class PersonDAOImpl implements PersonDAO {
#Autowired
private SessionFactory sessionFactory;
public Integer addPerson(Person p) {
Session session = sessionFactory.getCurrentSession();
Integer personID = (Integer) session.save(p);
return personID;
}
public Person getById(int id) {
Session session = sessionFactory.getCurrentSession();
Person retrievedPerson = (Person) session.get(Person.class, id);
return retrievedPerson;
}
#SuppressWarnings("unchecked")
public List<Person> getPersonsList() {
Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(Person.class);
return criteria.list();
}
public void delete(int id) {
Session session = sessionFactory.getCurrentSession();
Person personToDelete = getById(id);
session.delete(personToDelete);
}
public void update(Person personToUpdate) {
Session session = sessionFactory.getCurrentSession();
session.update(personToUpdate);
}
}
Read the documentation for more information.
#Transactional is used upon the method.
We declare on method level first it opens the transaction, perform the operation and close the transaction.
If an operation is failed it will be rollback, if an operation is a success it will automatically be committed
This is about #Transactional annotation finally&short.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<!-- Scans the classpath for annotated components that will be auto-registered as Spring beans -->
<context:component-scan base-package="hu.daniel.hari.learn.spring" />
<!-- Activates various annotations to be detected in bean classes e.g: #Autowired -->
<context:annotation-config />
<!-- creating the internal datasource object -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem://productDb" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:packagesToScan="hu.daniel.hari.learn.spring.orm.model"
p:dataSource-ref="dataSource"
>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<!-- Transactions -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
package hu.daniel.hari.learn.spring.orm.main;
import hu.daniel.hari.learn.spring.orm.model.Product;
import hu.daniel.hari.learn.spring.orm.service.ProductService;
import java.util.Arrays;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
public class SpringOrmMain {
public static void main(String[] args) {
//Create Spring application context
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/spring.xml");
//Get service from context. (service's dependency (ProductDAO) is autowired in ProductService)
ProductService productService = ctx.getBean(ProductService.class);
//Do some data operation
productService.add(new Product(1, "Bulb"));
productService.add(new Product(2, "Dijone mustard"));
System.out.println("listAll: " + productService.listAll());
//Test transaction rollback (duplicated key)
try {
productService.addAll(Arrays.asList(new Product(3, "Book"), new Product(4, "Soap"), new Product(1, "Computer")));
} catch (DataAccessException dataAccessException) {
}
//Test element list after rollback
System.out.println("listAll: " + productService.listAll());
ctx.close();
}
}
Related
I'm getting this error: org.hibernate.HibernateException: No CurrentSessionContext configured!
when trying to connect to Heroku Postgres DB.
this is my hibernate configuration (i called it: hibernateUser.cfg.xml):
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://ec2-54-243-213-188.compute-1.amazonaws.com:5432/dess6n165jarrv</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.default_schema">dess6n165jarrv</property>
<property name= "hbm2ddl.auto">update</property>
<property name="hibernate.current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>
enter code here
I'm implementing this as a singleton :
public static HibernateUserDAO getInstance(HttpServletResponse response) throws IOException
{
instance = new HibernateUserDAO();
if (instance == null)
{
userFactory = new Configuration().configure("hibernateUser.cfg.xml").addAnnotatedClass(AppUser.class).buildSessionFactory();
}
return instance;
}
public void addNewUser(AppUser user) throws UserExceptionHandler, IOException
{
Session session = null;
int id = 0;
try
{
session = userFactory.getCurrentSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}catch (HibernateException e)
{
if (session.getTransaction() != null) session.getTransaction().rollback();
throw new HibernateException (e);
}finally
{
try
{session.close();}
catch (HibernateException e)
{
throw new UserExceptionHandler("Warnning!! connection did'nt close properly");
}
}
if (id != 0)
System.out.println("User created successfully");
}
enter code here
I'm getting the error on this line:
session = userFactory.getCurrentSession();
I think the error is in my configuration file but I cant see where is the problem is (I read a couple of examples and I copy it)
You need to set your connection parameters dynamically like this:
Map<String,String> jdbcUrlSettings = new HashMap<>();
String jdbcDbUrl = System.getenv("JDBC_DATABASE_URL");
if (null != jdbcDbUrl) {
jdbcUrlSettings.put("hibernate.connection.url", System.getenv("JDBC_DATABASE_URL"));
}
registry = new StandardServiceRegistryBuilder().
configure("hibernate.cfg.xml").
applySettings(jdbcUrlSettings).
build();
This way, they are not hard coded, and will pick up changes made by the platform. For more info see Using the DATABASE_URL with Hibernate.
I'm working over HIbernate 4.3 and I'm getting problems with sessions.. I'm trying to do some operations on database but didnt work properly. Im receiving the message that Session is closed.
My HibernateUtil class that create the session factory:
public class HibernateUtil
{
private static SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory()
{
try
{
if (sessionFactory == null)
{
Configuration configuration = new Configuration().configure(HibernateUtil.class.getResource("/hibernate.cfg.xml"));
StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();
serviceRegistryBuilder.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = serviceRegistryBuilder.build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
return sessionFactory;
} catch (Throwable ex)
{
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
public static void shutdown()
{
getSessionFactory().close();
}
}
My hibernate.cfg.xml:
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/db?autoReconnect=true</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- Use the C3P0 connection pool. -->
<property name="c3p0.min_size">3</property>
<property name="c3p0.max_size">10</property>
<property name="c3p0.timeout">1800</property>
<!-- Disable 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>
<!-- Print SQL to stdout. -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Drop and then re-create schema on SessionFactory build, for testing. -->
<property name="hbm2ddl.auto">create</property>
<!-- Bind the getCurrentSession() method to the thread. -->
<property name="current_session_context_class">thread</property>
<mapping class="model.User"/>
<mapping class="model.Point"/>
<mapping class="model.Layer"/>
<mapping class="model.AddressDatabase"/>
</session-factory>
</hibernate-configuration>
My HibernateListener that starts on the web.xml:
public class HibernateListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
HibernateUtil.getSessionFactory();
}
public void contextDestroyed(ServletContextEvent event) {
HibernateUtil.getSessionFactory().close();
}
}
My DAOFactory of Hibernate:
public class HibernateDAOFactory extends DAOFactory {
public UserDao getUserDao() {
return (UserDao)instantiateDAO(UserDaoImpl.class);
}
private GenericHibernateDao instantiateDAO(Class daoClass) {
try {
GenericHibernateDao dao = (GenericHibernateDao)daoClass.newInstance();
dao.setSession(getCurrentSession());
return dao;
} catch (Exception ex) {
throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex);
}
}
// You could override this if you don't want HibernateUtil for lookup
protected Session getCurrentSession() {
return HibernateUtil.getSessionFactory().getCurrentSession();
}
}
And my HibernateDAO Factory, that instantiate the DAOs:
public class HibernateDAOFactory extends DAOFactory {
public UserDao getUserDao() {
return (UserDao)instantiateDAO(UserDaoImpl.class);
}
private GenericHibernateDao instantiateDAO(Class daoClass) {
try {
GenericHibernateDao dao = (GenericHibernateDao)daoClass.newInstance();
dao.setSession(getCurrentSession());t
return dao;
} catch (Exception ex) {
throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex);
}
}
protected Session getCurrentSession() {
return HibernateUtil.getSessionFactory().getCurrentSession();
}
}
Relevant parts of GenericDAO:
public abstract class GenericHibernateDao<T, ID extends Serializable> implements GenericDao<T, ID> {
private Class<T> persistentClass;
private Session session;
#SuppressWarnings("unchecked")
public GenericHibernateDao() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
public void setSession(Session s) {
this.session = s;
}
protected Session getSession() {
if (session == null)
session = HibernateUtil.getSessionFactory().getCurrentSession();
return session;
}
public T create(T entity) {
getSession().save(entity);
return entity;
}
...
When I do sequences of operations on database I got the error.. The code below is a servlet and show how I instantiate my DAO and try to run some operations :
DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE);
userDao = factory.getUserDao();
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction;
User user = new User();
user.setEmail("xxx#gmail.com");
user.setName("xxx");
user = userDao.create(user);
tx.commit(); <-- WORKS FINE
session = HibernateUtil.getSessionFactory().getCurrentSession();
tx = session.beginTransaction;
User user2 = userDao.findByEmail("xxx#gmail.com"); <-- HERE HAPPENS THE ERROR.
I followed theses tutorials:
https://developer.jboss.org/wiki/SessionsAndTransactions
https://community.jboss.org/wiki/GenericDataAccessObjects
I tried to use OpenSesssion instead of getCurrentSession but I got this error on the first action on database:
org.hibernate.HibernateException: save is not valid without active transaction
And when I use the other one, I got the exception that the Sesssion is closed!
Any help will be appreciated.
Regards
I recently started using hibernate along with c3p0 as the ORM in my application. However, when I close the session factory, the connection pool does not close itself! This is the one and only place in my application where I do anything with a session.
StatelessSession session = null;
Transaction transaction = null;
try {
session = sessionFactory.openStatelessSession();
transaction = session.beginTransaction();
List<Thingy> list = session.getNamedQuery("getAvailableThingy").list();
transaction.commit();
return list;
} catch (Exception error) {
if (transaction != null) {
transaction.rollback();
}
throw error;
} finally {
if (session != null) {
session.close();
}
}
This is my hibernate.cfg.xml 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.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="javax.persistence.validation.mode">none</property>
<property name="hibernate.connection.release_mode">after_transaction</property>
<property name="hibernate.c3p0.minPoolSize">1</property>
<property name="hibernate.c3p0.maxPoolSize">2</property>
<property name="hibernate.c3p0.acquireIncrement">1</property>
<property name="hibernate.c3p0.initialPoolSize">1</property>
<property name="hibernate.c3p0.timeout">30</property>
<property name="hibernate.c3p0.maxIdleTimeExcessConnections">5</property>
<property name="hibernate.c3p0.idleConnectionTestPeriod">300</property>
</session-factory>
</hibernate-configuration>
Note that the reason for the very short idle connection it that its the only way I found yet to make my integration tests to pass. They open and close the session factory a lot and thus I always run out of connections. As we are at the beginning of the project, I guess it's not a very sustainable strategy in the long run.
An "interesting" thing to note is that despite the fact that I set the initial connection pool to one, c3p0 still try to open two connection on start. My guess is that there is some kind of hidden session somewhere that don't get closed (but where? beat me).
So how can I get that annoying connection pool to close itself up?
Additional info :
how I create and destroy my session factory
import static com.google.common.base.Preconditions.*;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Provides;
#Singleton
public class PostgisConnection implements Provider<SessionFactory>, AutoCloseable {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final ConnectionInfo connectionInfo;
private SessionFactory sessionFactory = null;
#Inject
public PostgisConnection(ConnectionInfo connectionInfo) {
this.connectionInfo = connectionInfo;
}
public AutoCloseable open() {
checkState(sessionFactory == null, "Connections to postgis are already open");
logger.info("Creating sessionFactory for connection to postgis: {}", connectionInfo.getJdbcUrl());
sessionFactory = newPostgisSessionFactory(connectionInfo);
return this;
}
#Override
public void close() throws Exception {
try {
if (sessionFactory != null) {
logger.info("Closing sessionFactory for postgis: {}", connectionInfo.getJdbcUrl());
sessionFactory.close();
checkState(sessionFactory.isClosed(), "Session factory should be closed at this point");
}
} catch (Exception error) {
logger.error("Error closing SessionFactory", error);
}
}
#Provides
public SessionFactory get() {
return sessionFactory;
}
public static SessionFactory newPostgisSessionFactory(ConnectionInfo connectionInfo) {
Configuration configuration = configurationWith(connectionInfo);
return configuration.buildSessionFactory(registryFrom(configuration));
}
private static Configuration configurationWith(ConnectionInfo connectionInfo) {
Configuration configuration = new Configuration();
setConnectionInfo(connectionInfo, configuration);
configuration.addURL(PostgisConnection.class.getResource("mapping.hbm.xml"));
configuration.configure(PostgisConnection.class.getResource("hibernate.cfg.xml"));
return configuration;
}
private static void setConnectionInfo(ConnectionInfo connectionInfo, Configuration configuration) {
configuration.setProperty("hibernate.connection.url", connectionInfo.getJdbcUrl());
configuration.setProperty("hibernate.connection.username", connectionInfo.getUsername());
configuration.setProperty("hibernate.connection.password", connectionInfo.getPassword());
}
private static ServiceRegistry registryFrom(Configuration configuration) {
return new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
}
}
Hibernate version : 4.1.10.Final
C3p0 version : 0.9.1.2
I had the same issue and successfully used the work-around offered in this bug report:
private void closeSessionFactory(SessionFactory factory) {
if(factory instanceof SessionFactoryImpl) {
SessionFactoryImpl sf = (SessionFactoryImpl)factory;
ConnectionProvider conn = sf.getConnectionProvider();
if(conn instanceof C3P0ConnectionProvider) {
((C3P0ConnectionProvider)conn).close();
}
}
factory.close();
}
You have to reference the hibernate-c3p0-4.x.x jar.
I had the same issue and successfully used the ehnanced (January 2014) work-around offered in this bug report:
private static boolean closeSessionFactoryIfC3P0ConnectionProvider(SessionFactory factory) {
boolean done = false;
if(factory instanceof SessionFactoryImpl) {
SessionFactoryImpl sf = (SessionFactoryImpl)factory;
ConnectionProvider conn = sf.getConnectionProvider();
if(conn instanceof C3P0ConnectionProvider) {
((C3P0ConnectionProvider)conn).close();
try {
Thread.sleep(2000); //Let give it time...it is enough...probably
} catch (InterruptedException e) {
e.printStackTrace();
}
done = true;
}
factory.close();
}
return done;
}
You have to reference the hibernate-c3p0-4.x.x jar.
java.lang.NullPointerException
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1009)
at java.lang.Float.parseFloat(Float.java:439)
at ConvertReadings.Convertd(ConvertReadings.java:39)
at UDPServer.main(UDPServer.java:73)
hibernate cfg file
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">
com.mysql.jdbc.Driver</property>
<property name="connection.url">
jdbc:mysql://localhost:1111/DB</property>
<property name="connection.username">username</property>
<property name="connection.password">password</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.autoReconnect"> true</property>
<property name="connection.autoReconnectForPools">true</property>
<!-- <property name="c3p0.validate">true</property> -->
<property name="current_session_context_class">thread</property>
<property name="hibernate.format_sql">false</property>
<property name="hibernate.connection.pool_size">5</property>
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">1000</property>
<property name="hibernate.c3p0.max_size">5</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="hibernate.c3p0.min_size">3</property>
<property name="hibernate.c3p0.timeout">5000</property>
ConvertReadings code is
public class ConvertReadings {
public String Convertd(String a, String b, String c1, String c0 ) throws Exception
{
Converter con= new Converter();
int x;
double i = Float.parseFloat(a);
if (b.equalsIgnoreCase("HUM"))
{
double c=Float.parseFloat(c1);
double d=Float.parseFloat(c0);
x=con.convert(c, d, i);
return String.valueOf(x);
}
else if (b.equalsIgnoreCase("CO"))
{
double c=Float.parseFloat(c1);;
double d=Float.parseFloat(c0);
x=con.convert(c, d, i);
return String.valueOf(x);
}
return "Invalid sensor reading";
}
}
code where i am getting exception is
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
public class FetchCoeff {
public SessionFactory factory;
public String[] testing(String x, String y) { ///here x=DevID and y= sensor type
//Session session= null ;
String c[] = new String[30];
Session session = factory.openSession();
try{
String q= "SELECT d.c1, d.c0, d.DevID, d.SensorType FROM SensorReadings d WHERE d.DevID= :DevID AND d.SensorType= :SensorType";
Query query = session.createQuery(q);
query.setParameter("DevID",x);
query.setParameter("SensorType", y);
System.out.println("query executed");
for(Iterator it=query.iterate();it.hasNext();){
Object[] ob = (Object[]) it.next(); // I am Facing problem here
c[1]= (String)ob[0]; // contains coeff 1 c1
c[0]= (String)ob[1]; // contains coeff 0 c0
}
}catch(HibernateException e){
System.out.println("Hibernate exception occured");
e.printStackTrace();
}catch(Exception d){
System.out.println("exception occured");
d.printStackTrace();
}
finally
{
session.close();
}
return c;
}
}
I had posted it few weeks before and i got solution for this from "JB Nizet" but it solved only one part now i am facing Null pointer exception in below part
for(Iterator it=query.iterate();it.hasNext();){
Object[] ob = (Object[]) it.next();
c[1]= (String)ob[0];
c[0]= (String)ob[1];
I think this object is throwing null pointer exception but i don't know how solve it. can anyone help me in this.. here i am created query and iterated result set and passing it to the string array.
If I understand correctly, You're executing the above methods several times, and after some invocations, it throws the above exception.
The problem probably comes from the fact that you're reading the Hibernate configurationand creating a whole new session factory, with a new connection pool, at each method invocation.
The following should be done once and only once. The same session factory should then be reused at each method invocation:
Configuration cfg= new Configuration();
cfg.configure("Hibernate.cfg.xml");
SessionFactory sessionfactory = cfg.buildSessionFactory();
I'm very new to Hibernate and just wanted to query the initial basics.
I've created my Hibernate bean as such...
package com.behaviour.chapter1;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class User {
private int userId;
private String firstName;
#Id
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
I've configured my hibernate.cfg.xml and db connection there. My question is simply, how do I actually call this from a main method and use it in Hibernate3.6.6? I was following a tutorial online but it was for Hibernate3.2 and it seems to be a bit different. If anyone could show me just a really simple main method calling this bean, creating a new user (that would create a user in this table) it would be greatly appreciated. Also - if anyone has any good Hibernate tutorial links that would be great :)
Thanks,
There are several ways of doing this, it is a matter of design choice, a basic way to achieve this will be to create the session factory from hibernate.cfg.xml file. Make sure the file can be located at your classpath.
And using the class below, create a Session Factory object which is then used to open up new Session's
public class HibernateUtil
{
private static final SessionFactory sessionFactory;
static
{
try
{
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
}
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;
}
}
Now to create a new user, do:
public class DaoFactory
{
public void create(Object obj)throws Exception
{
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(obj);
session.getTransaction().commit();
}
}
Main
public static void main(String[] args)
{
try
{
User user = new User();
user.setFirstName("david99world");
DaoFactory factory = new DaoFactory();
factory.create(user);
}
catch(Exception ex)
{
ex.printStackTrace(System.out);
}
}
EDIT
Your hibernate.cfg.xml should look something 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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</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>
<!-- 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">none</property>
<mapping class="com.behaviour.chapter1.User"/>
</session-factory>
</hibernate-configuration>
I'm assuming you've set up your persistence.xml already. If so, you can use the following Java code. You'll have to substitute the "..." with your JDBC setup data and persistence unit.
private static final String PERSISTENCE_UNIT = "...";
final Map<String, String> properties = new HashMap<String, String>();
properties.put("javax.persistence.jdbc.driver", "...");
properties.put("javax.persistence.jdbc.url", "...");
properties.put("javax.persistence.jdbc.user", "...");
properties.put("javax.persistence.jdbc.password", "...");
final EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT, properties);
final EntityManager em = emf.createEntityManager();
User user = new User();
user.setUserID(0);
user.setFirstName("David");
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();
HTH
Raku
Hibernate tutorials
Hibernate tutorial-1
Hibernate tutorial -2
Do you need a Session object to access the persistence unit. These objects are provided by SessionFactory objects.
Check the Hibernate reference guide.