Here is my JPA Utill Class....
private static Logger logger=Logger.getLogger(JPAUtil.class);
private static EntityManager entityManager = null;
private static final ThreadLocal<EntityManager> threadLocal;
private static EntityManagerFactory emf = null;
static
{
try {
emf = Persistence.createEntityManagerFactory("XYZ");
threadLocal = new ThreadLocal<EntityManager>();
} catch (Throwable ex) {
logger.info("JPAUtil Exception",ex);
throw new ExceptionInInitializerError(ex);
}
}
public static EntityManager getEntityManager() {
try {
entityManager = threadLocal.get();
if (entityManager == null || !entityManager.isOpen()) {
JPAUtil.entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
}else if(!emf.isOpen())
{
entityManager = threadLocal.get();
emf = Persistence.createEntityManagerFactory("XYZ");
JPAUtil.entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
}
} catch (Throwable ex) {
logger.info("JPAUtil Exception",ex);
throw new ExceptionInInitializerError(ex);
}
return JPAUtil.entityManager;
}
public static void closeEntityManager() {
EntityManager entityManager = threadLocal.get();
if (entityManager != null) {
entityManager.close();
threadLocal.set(null);
}
}
public static void closeEntityManagerFactory() {
emf.close();
}
public static void commit() {
if (!entityManager.getTransaction().isActive()){
entityManager.getTransaction().begin();
}
entityManager.getTransaction().commit();
}
public static void rollback() {
if (!entityManager.getTransaction().isActive()){
entityManager.getTransaction().begin();
}
entityManager.getTransaction().rollback();
}
And After each and every transactions i am closing entitymanager....with
finally block...and later i came to Know that even in select query we need to
begin transaction and commit it...so i did try that in my application Home
page Just executing 2 select query and in the server mysql is Occupying the memory the most....with the eclipse MAT i Anallise the Memory Leak....
As per my understanding since i am using tomcat i cant do connection pooling..and we will be moving to jboss...but till the i would like to patch this....any help would be appreciated :) :)
Related
I have developed a project using Hibernate. I am trying to test it using Junit with H2 in memory db but the test case is creating fields in the db that I am using it for development.
Here is my code :
UserDAO.java
public interface UserDAO {
public void addUser(String username, String password);
public List<String> getUsers();
}
UserDAOImpl.java
public class UserDAOImpl implements UserDAO {
public static final Logger LOG = LoggerFactory.getLogger(UserDAOImpl.class);
private static Session session;
private static void beginSession() {
session = DbUtils.getSessionFactory().openSession();
session.beginTransaction();
}
#Override
public void addUser(String username, String password) {
String encryptedPassword = Utils.encrypt(password);
User user = new User(username, encryptedPassword);
beginSession();
try {
session.save(user);
System.out.println(user.getPassword());
session.getTransaction().commit();
} catch (SQLGrammarException e) {
session.getTransaction().rollback();
LOG.error("Cannot save user", e);
} finally {
session.close();
}
}
#Override
public List<String> getUsers() {
beginSession();
List<String> results = new ArrayList<String>();
String hql = "select username from User";
Query query = null;
try {
query = session.createQuery(hql);
results = query.list();
} catch (HibernateException e) {
LOG.error("Cannot execute query", e);
}
return results;
}
}
Files for test cases
SessionFactoryRule.java
public class SessionFactoryRule implements MethodRule {
private SessionFactory sessionFactory;
private Transaction transaction;
private Session session;
#Override
public Statement apply(final Statement statement, FrameworkMethod method, Object test) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
sessionFactory = createSessionFactory();
createSession();
beginTransaction();
try {
statement.evaluate();
} finally {
shutdown();
}
}
};
}
private void shutdown() {
try {
try {
try {
transaction.rollback();
} catch (Exception ex) {
ex.printStackTrace();
}
session.close();
} catch (Exception ex) {
ex.printStackTrace();
}
sessionFactory.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private SessionFactory createSessionFactory() {
Configuration configuration = new Configuration().configure();
configuration.addAnnotatedClass(User.class)
.addAnnotatedClass(Message.class);
configuration.setProperty("hibernate.dialect",
"org.hibernate.dialect.H2Dialect");
configuration.setProperty("hibernate.connection.driver_class",
"org.h2.Driver");
configuration.setProperty("hibernate.connection.url", "jdbc:h2:./data/db");
configuration.setProperty("hibernate.hbm2ddl.auto", "create");
SessionFactory sessionFactory = configuration.buildSessionFactory();
return sessionFactory;
}
public Session createSession() {
session = sessionFactory.openSession();
return session;
}
public void commit() {
transaction.commit();
}
public void beginTransaction() {
transaction = session.beginTransaction();
}
public Session getSession() {
return session;
}`
Here is my test case
UserDAOTest.java
public class UserDAOTest {
#Rule
public final SessionFactoryRule sf = new SessionFactoryRule();
#Test
public void testAddUser() {
Session session = sf.getSession();
UserDAOImpl userDAOImpl = new UserDAOImpl();
String username = "stackoverflow";
String password = "testing";
userDAOImpl.addUser(username, password);
}
}
This test case is updating the fields username and password in the db that I am using while development. How can I stop it and use h2 in-memory db for testing.
You have session = DbUtils.getSessionFactory().openSession() in the UserDAOImpl. This is the reason of using a development database. Your SessionFactoryRule is not used at all.
So what you can to do.
The best choice is use to Spring for Hibernate configuration and unit testing.
Other option is to set sessionFactory to the UserDAOImpl using constructor.
Also, using static here is a really very very bad idea
private static Session session;
I am new to JPA and Java. I understood how EntityManager and EMF works a littel bit. I have JPAUtill from where I get EntityManager, which is using ThreadLocal variable, which makes EntityManager thread safe. I have DAO where in I am persisting new users when having 10 thousand thread accesses simultaneously.
I get to see following exception:
javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed!
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
Here is my DAO code
try{
entityManager = JPAUtil.getEntityManager();
user.setArea(getArea());
user.setCity(getCity());
user.setPassword("xxxxx");
user.setEmail_Id(getEmail_Id());
user.setMobile_Num(TempMobile_Num);
user.setFirst_Name(getFirst_Name());
user.setSession_Id("0");
user.setEmail_Verification_Status("NOT VERIFIED");
user.setBalance(new BigDecimal(0.00));
if (!entityManager.getTransaction().isActive()){
entityManager.getTransaction().begin();
}
entityManager.persist(user);
JPAUtil.commit();
} catch (Exception e) {
logger.info(e);
e.printStackTrace();
} finally{
if(entityManager.isOpen())
JPAUtil.closeEntityManager();
}
JPAUtil:
public class JPAUtil {
private static Logger logger = Logger.getLogger(JPAUtil.class);
private static EntityManager entityManager = null;
private static final ThreadLocal<EntityManager> threadLocal;
private static EntityManagerFactory emf = null;
static {
try {
emf = Persistence.createEntityManagerFactory("XYZDB");
threadLocal = new ThreadLocal<EntityManager>();
} catch (Throwable ex) {
logger.info("JPAUtil Exception", ex);
throw new ExceptionInInitializerError(ex);
}
}
public static EntityManager getEntityManager() {
try {
entityManager = threadLocal.get();
if (entityManager == null || !entityManager.isOpen()) {
JPAUtil.entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
} else if (!emf.isOpen()) {
entityManager = threadLocal.get();
emf = Persistence.createEntityManagerFactory("XYZDB");
JPAUtil.entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
}
} catch (Throwable ex) {
logger.info("JPAUtil Exception", ex);
throw new ExceptionInInitializerError(ex);
}
return JPAUtil.entityManager;
}
public static void closeEntityManager() {
EntityManager entityManager = threadLocal.get();
if (entityManager != null) {
entityManager.close();
threadLocal.set(null);
}
}
public static void closeEntityManagerFactory() {
emf.close();
}
public static void commit() {
if (!entityManager.getTransaction().isActive()) {
entityManager.getTransaction().begin();
}
entityManager.getTransaction().commit();
}
public static void rollback() {
if (!entityManager.getTransaction().isActive()) {
entityManager.getTransaction().begin();
}
entityManager.getTransaction().rollback();
}
}
Can someone please help me understand the issue and how to resolve it?
Remove this static variable form JPAUtil:
private static EntityManager entityManager = null;
You were still using a static variable; you didn't really use the ThreadLocal.
Change your getEntityManager to this:
public static EntityManager getEntityManager() {
EntityManager entityManager;
try {
entityManager = threadLocal.get();
if (entityManager == null || !entityManager.isOpen()) {
entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
}
} catch (Throwable ex) {
logger.info("JPAUtil Exception", ex);
throw new ExceptionInInitializerError(ex);
}
return entityManager;
}
In our application we have an HibernateSessionFactory class, that is opening and closing connections. Everything is okay, but when we are updating data in the database, it doesn't change in our application. Unfortunately, we see old data from the database. How can I fix this?
public class HibernateSessionFactory {
private static final ThreadLocal threadLocal = new ThreadLocal();
private static org.hibernate.SessionFactory sessionFactory;
private static Configuration configuration = new Configuration();
private static ServiceRegistry serviceRegistry;
private static final Logger log = Logger.getLogger(
HibernateSessionFactory.class);
static {
try {
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
log.error("Error Creating SessionFactory", e);
}
}
private HibernateSessionFactory() {}
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ?
sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
log.error("Error Creating SessionFactory", e);
}
}
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.flush();
session.close();
}
}
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Configuration getConfiguration() {
return configuration;
}
}
.
#SuppressWarnings("unchecked")
public List<Tauthor> getAuthors() throws HibernateException {
log.debug("getting all authors");
Query queryObject = null;
List<Tauthor> authors = null;
Session session = HibernateSessionFactory.getSession();
try {
String queryString = "from Tauthor";
queryObject = session.createQuery(queryString);
authors = queryObject.list();
} catch (HibernateException e) {
log.error("get all authors failed", e);
throw e;
} finally {
HibernateSessionFactory.closeSession();
}
return authors;
}
You haven't shared your code where you write data to the database. Without that, I can think of only a few reasons as to why your data output is old instead of new data:
Your transactions are not being committed.
Hibernate hasn't written to the database at the time of data queried by you.
Hibernate's cache hasn't been updated, which results in query returning old data.
You should verify that data has been written to the Database with a db developer tool and try disabling all hibernate caching to see if the result changes.
I have the following situation with Java persistence:
public ReturnCodes startWork() {
sessionBackup = (BaseService<Backup>) ctx.lookup("XYZ/BackupServiceImpl/local");
Backup backup = new Backup();
backup.setStatus(BackupStatus.EXECUTING);
....
sessionBackup.save(Backup) //at this point is not actualy saved into DB
....//try to connect somewhere
if ( !ConnectSuccess) {
sessionBackup.remove(backup);
return ReturnCodes.REQUESTABORT
}
....
}
#Stateless
public class BackupServiceImpl extends BaseServiceImpl<Backup> implements
BaseService<Backup>
{
#Override
protected Class<Backup> getEntityClass()
{
return Backup.class;
}
}
And the save and remove methods of BaseServiceImpl:
public abstract class BaseServiceImpl<T extends Serializable> implements
BaseService<T>
{
protected EntityManagerFactory emf;
public T save(T entity)
{
EntityManager em = emf.createEntityManager();
em.persist(entity);
return entity;
}
public void remove(T entity)
{
EntityManager em = emf.createEntityManager();
try
{
final Method method = getEntityClass().getMethod("getId");
final String id = (String) ((T) method.invoke(entity));
entity = em.find(getEntityClass(), id);
em.remove(entity);
}
catch (final Exception ex)
{
logger.log(Level.WARNING, "Unexpected error", ex);
}
}
}
I don't want to save into the DB in case ConnectSuccess fails, but the remove method fails to find the entity (because is not yet into the DB), and after returning ReturnCodes.REQUESTABORT the entity is saved.
How can I cancel the save?
In general in this case you do a setRollbackOnly().
You may also throw an exception which will trigger the rollbackonly.
See http://www.developerscrappad.com/547/java/java-ee/ejb3-x-jpa-when-to-use-rollback-and-setrollbackonly/
By the way doing this in your code:
catch (final Exception ex)
{
logger.log(Level.WARNING, "Unexpected error", ex);
}
is too broad and will block rollback functionality.
I am working on a simple EJB module using sample code. I am trying to implement CURD operations through a SOAP web service. I have a persistence unit defined in persistence.xml.
Here is the code for my implementation. The problem is that I cannot create an instance of PersistenceService because the persistence unit name is not present in the JNDI listings.
If, instead of using code injection, I use
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PU_NAME);
em = emf.createEntityManager();
the code runs, but then the transaction is managed by the container. I was reading through some tutorials and they mentioned that, in this scenario, if the user wants to roll the transaction back later, he cannot do so.
What can I do instead?
users class
#WebService()
#Stateless()
public class users {
public users()
{
}
/**
* Web service operation
*/
#WebMethod(operationName = "addUser")
public Integer addUser(
#WebParam(name = "UserName") final String UserName,
#WebParam(name = "LastName") final String LastName) {
DatabaseEntityManager dem = new DatabaseEntityManager();
Integer result = null;
try
{
result = dem.addUser(UserName, LastName, false);
dem.commitTx();
return result;
} catch(Exception E)
{
}
return new Integer(-1);
}
DatabaseEntityManager class
public class DatabaseEntityManager {
PersistenceService ps_bck = null;
public DatabaseEntityManager()
{
}
public SiteUsers addUser(
String Username,
String LastName, boolean commit) throws Exception
{
AppUser appUser = new appUser(UserName, LastName);
//AppUser is an entity class
PersistenceService ps = PersistenceService.getInstance();
try
{
ps.beginTx();
EntityManager em = ps.getEntityManager();
em.persist(appUser);
if (commit)
ps.commitTx();
else
ps_bck = ps;
}
catch (Exception E)
{
ps.rollbackTx();
}
finally
{
ps.close();
}
return appUser.getId();
}
void commitTx() throws Exception
{
try
{
ps_bck.commitTx();
}
catch(Exception E)
{
throw E;
}
finally
{
ps_bck =null;
}
}
}
PersistenceService class — borrowed from sample code generated by NetBeans
public class PersistenceService {
private static String DEFAULT_PU = "pers-ejbPU";
private static ThreadLocal<PersistenceService> instance = new ThreadLocal<PersistenceService>() {
#Override
protected PersistenceService initialValue() {
return new PersistenceService();
}
};
private EntityManager em;
private UserTransaction utx;
private PersistenceService() {
try {
//This code runs
// EntityManagerFactory emf = ersistence.createEntityManagerFactory(DEFAULT_PU);
// em = emf.createEntityManager();
//This code throws an exception
this.em = (EntityManager) new InitialContext().lookup("java:comp/env/persistence/"+ DEFAULT_PU);
this.utx = (UserTransaction) new InitialContext().lookup("java:comp/UserTransaction");
} catch (NamingException ex) {
throw new RuntimeException(ex);
}
}
/**
* Returns an instance of PersistenceService.
*
* #return an instance of PersistenceService
*/
public static PersistenceService getInstance() {
return instance.get();
}
private static void removeInstance() {
instance.remove();
}
/**
* Returns an instance of EntityManager.
*
* #return an instance of EntityManager
*/
public EntityManager getEntityManager() {
return em;
}
/**
* Begins a resource transaction.
*/
public void beginTx() {
try {
utx.begin();
em.joinTransaction();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* Commits a resource transaction.
*/
public void commitTx() {
try {
utx.commit();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* Rolls back a resource transaction.
*/
public void rollbackTx() {
try {
utx.rollback();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* Closes this instance.
*/
public void close() {
removeInstance();
}
}
If your persistence.xml has an entry
<persistence-unit name="PU_NAME" transaction-type="JTA">
In your PersistenceService class, add the annotation:
#PersistenceContext (name = "PU_NAME") private EntityManager em;