I am fully testing an entity on my unit test, and almost everything worked so far: create, update, list. However, when I try to delete a record, it is not getting deleted. Here is the code I am using:
public void delete (Integer id) {
// This doesnt work even though I know user is set and id is not null
User user = find(id);
getSession().delete(user);
// This will work
// Query query = getSession().createSQLQuery("DELETE FROM users WHERE id = " + id);
// query.executeUpdate();
}
private Session getSession() {
if (session == null) {
try {
session = SessionFactoryUtils.getSession(sessionFactory, Boolean.TRUE);
TransactionSynchronizationManager.bindResource(session.getSessionFactory(), new SessionHolder(session));
} catch (Exception e) {
session = SessionFactoryUtils.getSession(sessionFactory, Boolean.FALSE);
}
}
return session;
}
If I execute the query directly it works but using the delete() method doesnt. I think it may be related to committing the transaction but I already tried something like that and no luck. Any ideas?
I found the problem with this one.
First, find() method was evicting my user model, and probably taking it out of the session.
After delete(), I also needed to session.flush()
Related
I have 5 tables data those needs to be saved at a same time into database.My code snippet is as below.
public boolean addStudentDetail(RegisterLoginDetail registerLoginDetail,
StudentRegisterBasicDetail studentRegisterBasicDetail, StudentBoardDetail studentBoardDetail,
StudentSchoolDetail studentSchoolDetail, StudentAdditionalDetail studentAdditionalDetail,
StepCompletionMatrix stepCompletionMatrix) {
boolean isSuceess = true;
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.saveOrUpdate(registerLoginDetail);
session.saveOrUpdate(studentRegisterBasicDetail);
session.saveOrUpdate(studentBoardDetail);
session.saveOrUpdate(studentSchoolDetail);
session.saveOrUpdate(studentAdditionalDetail);
session.saveOrUpdate(stepCompletionMatrix);
transaction.commit();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
isSuceess = false;
} finally {
if (session != null && session.isOpen()) {
session.close();
}
}
return isSuceess;
}
But for my two transaction data entry for insert operation not found in StudentRegisterBasicDetail table and all other table contains entry for one common id shared between each table.My webapplication is in pilot testing mode and concurrent users are making entry through form.So I am not able to figure out for which reason my entry being skipped in that table.There is no exception log for that table entry and if exception occurs then rollback for all table should be happen or not?
Please help me...
I've created method to save entity with new id or update existing via hibernate session. When I use next code:
try {
Session session = sessionWrapper.getSession();
sessionWrapper.beginTransaction();
if (user.getId()==null || session.get(User.class, user.getId())==null) {
return (long) session.save(user);
} else {
session.get(User.class, user.getId());
session.merge(user);
return user.getId();
}
} finally {
sessionWrapper.commit();
sessionWrapper.closeSession();
}
it works ok, but when I use session.saveOrUpdate instead in case of new entity generated id is increased by two, not one. Why and how to fix it?
I am trying to save to database changes made to a detached entity.
The object of the entity is passed to the function by argument (named as data):
private boolean generate(CommonGameData data) {
boolean result = true;
EntityManager em = HibernateUtil.currentEntityManager();
try {
em.getTransaction().begin();
em.merge(data);
em.flush();
...some changes to data object...
em.persist(data);
em.flush();
em.getTransaction().commit();
} catch (Exception ex) {
...
return false;
}
return true;
}
As I have read if I am using the detached entity, I should call merge first.
But after commit is done successfully, I don't see any changes in database.
Where is the mistake?
As you do not save a new entity (from your comment), you do not need a call to persist().
Also I do not see any reasons to make 'some changes' after calling merge(), so I called merge() after making those changes.
So, try the following:
em.getTransaction().begin();
...some changes to data object...
em.merge(data);
em.flush();
em.getTransaction().commit();
Also very important: if you reuse the EntityManager from the a ThreadLocal variable, you should take care of things like failed past transactions (at least clear it + maybe close it). Also if the bug still persists, try recreating an entityManager.
First time that I ran into this error I've surrounded my tx.commit() with a if condition but am not sure why I am still receiving this error.
Struts Problem Report
Struts has detected an unhandled exception:
Messages:
Transaction not successfully started
File: org/hibernate/engine/transaction/spi/AbstractTransactionImpl.java
Line number: 200
Stacktraces
org.hibernate.TransactionException: Transaction not successfully started
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:200)
After a product has been selected by user, in my main function I will call two functions as following.
First function to retrieve the object of selected product.
Second function to check if selected user has the product therefore it returns true if client has the product otherwise returns false;
Function 1
....
Product pro = new Product();
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
try {
pro = (Product) session.get(Product.class, id);
if (!tx.wasCommitted()) {
tx.commit();
}
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
}
} finally {
HibernateUtil.closeSession();
}
.....
Function 2
.....
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
try {
User user = (User) session.get(User.class, id);
if (!tx.wasCommitted()) {
tx.commit();
}
if(client.hasProduct(proId)){
return client.getProduct(proId);
}
return false;
} catch (Exception e) {
tx.rollback(); <<<Error is on this line
e.printStackTrace();
}
} finally {
HibernateUtil.closeSession();
}
....
Take a look at Transaction.isActive() method. You can wrap call to rollback() method with condition, checking whether transaction is still active. And the second, I'd prefer the following code:
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
// do things
tx.commit();
} finally {
if (tx.isActive()) {
try {
tx.rollback();
} catch (Exception e) {
logger.log("Error rolling back transaction", e);
}
}
try {
session.close();
} catch (Exception e) {
logger.log("Error closing session", e);
}
}
Of course, code in the finally section better to wrap into public static method and just call it in every finally.
BTW, why are you doing something outside tranaction? I usually commit after all things get done, to achieve a better consistency and avoid LazyInitializationException.
One possibility is that the exception you are catching in the second functions is from the code after the commit(), so you end up trying to rollback a transaction that is already committed, which is not allowed.
You could try reorganizing your code to make sure that rollback is never called after commit. Maybe even something simple like reducing the scope of the inner try-catch:
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
try {
User user = (User) session.get(User.class, id);
if (!tx.wasCommitted()) {
tx.commit();
}
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
}
if(client.hasProduct(proId)){
return client.getProduct(proId);
}
return false;
} finally {
HibernateUtil.closeSession();
}
The error indicates the transaction wasn't started at the time tried to roll back - and the problem may be that you are trying to wrap a get, which does not alter the db state and does not leave behind garbage that needs to be committed or rolled back. Nothing changes when you perform select *.
In addition to this, you may want to extract this transaction handling into a common method that is independent of the work being done, so you don't have to write this over and over again, that leaves your code open for bugs. Basically, it seems like you are getting DB objects but then intermingling some business logic withing the same method. Perhaps consider doing something like below:
DB Handling Function
public static <T> T getDBObject( Class<T> clazz, Serializable id )
throws SQLException
{
Session session = null;
try
{
session = HibernateUtil.getSession();
return (T)session.get( clazz, id );
}
finally
{
if ( session != null )
{
session.close();
}
}
}
Now that you can pull object of the DB (note that they will be detached, but still valid), you can then perform work on the objects. I many not have captured exactly what you need to check, but it seems like it is something like:
Example Comparison Function
public boolean doesUserHaveProduct(Serializable userId, Serializable productId)
{
try
{
User user = getDBObject(User.class, userId);
Product product = getDBObject( Product.class, productId );
return user.hasProduct( product );
}
catch (SQLException e)
{
e.printStackTrace();
return false;
}
}
i am using the following approach to sole lazy initialization problem in hibernate.Pleas tell me whether it will work or not .
I have to implement my transcation in my persistance layer compulsary due to some reasons.
public class CourseDAO {
Session session = null;
public CourseDAO()
{
this.session = this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
public Course findByID(int cid){
Course crc = null;
Transaction tx = null;
try {
tx = session.beginTransaction();
Query q = session.createQuery("from Course as course where course.cid = "+cid+" ");
crc = (Course) q.uniqueResult();
//note that i am not commiting my transcation here.Because If i do that i will not be able to
//do lazy fetch
}
catch (HibernateException e)
{
e.printStackTrace();
tx.rollback();
throw new DataAccessLayerException(e);
}
finally
{
}
return crc;
}
}
and in the filter i am using the folling code
session = HibernateUtil.getSessionFactory().getCurrentSession();
if(session.isOpen())
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
IS this approach right??
Can it can have any problem
could you explain why do you need to have ur transactions in ur repositories? the problem there is that they are going to be so fine-grained, so you are not gonna get any advantage from the session caching
then you are opening the transaction there but closing it in your filter. what happens if you access multiple repositories in your service? Maybe i am not understanding what you mean but i think you need to re-think the reasons that force you to manage your transactions in your repositories
When do you create you CourseDAO? If it is a singleton bean or something else that lives longer than a page view, it will need to keep a SessionFactory and generate a new Session when it needs one rather than keeping a Session.