Problems with Session.save() - java

I'm new to hibernate and as I researched, I have found out that the HQL insert query gets data from other tables. According to what I've read, I can make use of session.save for the insert functionality.
In my DAO I have this addToCart() method
#Override
public void addToCart(ShoppingCart cart) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.save(cart);
transaction.commit();
session.close();
}
The code above doesn't work. Maybe I am missing something because I'm still new to hibernate.

Related

JPQL and entity data

I have entity Student with two fields: id, name
I save it in the base using entityManager persist()
next, using JPQL I update one entity and get it.
Data in the entity is old. Why?
but in the DB all data of entity is changing.
public class Main {
public static void main(String[] args) {
EntityManagerFactory myFactory = Persistence.createEntityManagerFactory("myPerName777");
EntityManager entityManager = myFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(new Student("max"));
entityManager.persist(new Student("max"));
entityManager.persist(new Student("max"));
entityManager.persist(new Student("mike"));
entityManager.persist(new Student("mike"));
transaction.commit();
transaction.begin();
Query query = entityManager.createQuery("UPDATE Student s set s.userrname='JOHN' where s.id=1");
query.executeUpdate();
transaction.commit();
Student student = entityManager.find(Student.class,1);
System.out.println(student.getUserrname());
entityManager.close();
myFactory.close();
}
}
This code return Max, but in the DB date is changing.
How can I return actual data?
With executeUpdate you execute a SQL statement (modifying directly the DB) but do not change the Entity loaded/managed by Hibernate, hence you hold stale data in your application.
The best approach is to always work with the Hibernate entities which are managed by Hibernate and kept in the first-level cache. Your data stays in synch with the DB.
If you really need to run a statement (for example because it is a complex statement or performs much better) you need to evict the Entity and reload it again from the DB.

When do we need to use #Transactional?

I'm learning about #Transactional and I want to ask you a question. Why is important to use #Transactional at the following methods?
#Repository
public class CustomerDAOImpl implements CustomerDAO {
// need to inject the session factory
#Autowired
private SessionFactory sessionFactory;
#Override
#Transactional
public List<Customer> getCustomers() {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// create a query ... sort by last name
Query<Customer> theQuery =
currentSession.createQuery("from Customer order by lastName",
Customer.class);
// execute query and get result list
List<Customer> customers = theQuery.getResultList();
// return the results
return customers;
}
#Override
#Transactional
public void saveCustomer(Customer theCustomer) {
// get current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// save/upate the customer ... finally LOL
currentSession.saveOrUpdate(theCustomer);
}
#Override
#Transactional
public Customer getCustomer(int theId) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// now retrieve/read from database using the primary key
Customer theCustomer = currentSession.get(Customer.class, theId);
return theCustomer;
}
#Override
#Transactional
public void deleteCustomer(int theId) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// delete object with primary key
Query theQuery =
currentSession.createQuery("delete from Customer where id=:customerId");
theQuery.setParameter("customerId", theId);
theQuery.executeUpdate();
}
}
I thought that we need to use #Transactional when we have 2 or more writes on a database. For example if we want to transfer $100 from user A to user B. In this case we need to do 2 things, first we need to decrease $100 from user A, and second we need to add $100 to user B. And we need this 2 writes as a single atomic operation. And I understand why we need #Transactional in this situation.
But what I don't understand is why do we need #Transactional for the 4 methods in the above code. In getCustomers() method we just retrieve the customers, in saveCustomer() we just save a customer in the database, deleteCustomer() we just delete a customer. So in these methods we have only one write in the database. Then why do we need #Transactional? Thank you!

Hibernate - 1 Class 2 Tables

I have a simple table and I want to store them in another table aswell (create a historic of users). Let's call it Users. I created a table exactly like Users (only different id name) called HISTORY_Users.
So I created the table and now I realize that I have 2 tables for 1 object. So how do I add my object only to the hist table?
I dont want to add them at the same time. I want to add the user to the hist only when he deletes the accounts.
I'm using Hibernate with xml mapping
//when the user deletes the account I call this function and pass the User
private static void addToHist(User User) {
//how do I add only to HIST_Users table??
Database.addToDatabase(user);
}
//Save the object to the database
public static void addToDatabase(Object object) {
SessionFactory factory = HibernateUtil.GetSessionFactory();
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
session.save(object);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
Maybe better solution will be use the Hibernate Envers: http://hibernate.org/orm/envers/
You can configure when you want to put it into history: on create, update or delete.
Tables are created automatically, you need to add some annotations only like #Audited etc.

Delete Function org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

Do anyone know how to solve this problem?? I am trying to delete an entity but this error message always appears.
This is the code used:
#Override
public void remove(t_diklat diklat) {
Session session = HibernateUtil.getSessionFactory().openSession();
try {
session.getTransaction().begin();
session.delete(diklat);
session.getTransaction().commit();
} catch (Exception ex) {
throw ex;
}
and:
public String delete() {
t_diklat diklat = (t_diklat)(listDiklat.getRowData());
diklatDao dao = new diklat_Impl();
dao.remove(diklat);
return "diklat_client";
}
This is my dao
public interface diklatDao {
public t_diklat getTbl_diklat(Long id);
public void Save(t_diklat diklat);
public void remove(t_diklat diklat);
public void update(t_diklat diklat);
public List<t_diklat> ListTable();
}
I also add #OneToMany(mappedBy = "diklat_id_5", cascade = CascadeType.ALL) to my model.class but still nothing.
I am quite sure that the:
public String delete()
method is called within an already opened session as you are retrieving data:
t_diklat diklat = (t_diklat)(listDiklat.getRowData());
just before you hit the dao.remove() method.
Inside the dao, you open another session and try pass an entity that is already associated with the presiously opened and still not closed session.
The solution would be to use:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
instead of:
Session session = HibernateUtil.getSessionFactory().openSession();
Edit:
Try not to open any new transactions and do not perform a commit in the dao. The outer session management should be enough.. So in your dao just:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.delete(diklat);

Hibernate throwing an error message. But saving the data into database

We are using Hibernate and MySQL in our project. We are using saveOrUpdate() method for updating data.
Our problem When We update the existing data first we are checking some conditions. If those conditions are passed we are throwing error like below snippet code.
Else we are saving the data. We put debug and checked at the saveOrUpdate() method. It is not going to saveOrUpdate(). But some how data is saving into database.
This is DAO layer
public List<Student> getOverlappingStudentDetails(String studentId, String classNumber){
Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(Student.class, "student");
criteria.add(Restrictions.eq("student.id", studentId));
criteria.add(Restrictions.eq("student.classNumnber", classNumber));
return criteria.list();
}
public Student save(Student student) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(student);
session.flush();
return student;
}
This is service implementation
private void checkForOverlappingStudentDetails(Student student) {
List<Student> overlappingStudents = studentDAO.getOverlappingStudentDetails(student.getStudentId(),student.getClassName());
if (overlappingStudents.size() >0 ) {
throw new ValidationException(student.getName() + " is already present." ;
}
}
It is throwing error. But, data is overriding into database. Is there any solution to stop the data to for updating. We tried session.clear() and we are using session.flush() method after saving the method.

Categories

Resources