hibernate session.save() inserts different values than are at object - java

I have little problem. When I try insert new value to database, function save() inserts me different values ​​than are at object :(. What should I do?
Here is my function
public void updateListOfElements(List<Dokumenty> list) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
for (Dokumenty dokument : list) {
Dokumenty dokumentToUpdate =
(Dokumenty) session.get(Dokumenty.class, dokument.getId());
dokumentToUpdate.setAktywny('N');
session.update(dokumentToUpdate);
// id z dupy wpisuje
dokument.setId(10114);
session.save(dokument);
}
transaction.commit();
} catch (HibernateException e) {
if (transaction != null) {
transaction.rollback();
}
} finally {
session.close();
}
}

You should use saveOrUpdate not save
dokument.setId(10114);
session.saveOrUpdate(dokument);
When you call saveOrUpdate() If the identifier exists, it will call update method else the save method will be called.
If you call save() method stores an object into the database. That means it insert an entry.
Before proceed have a look :What are the differences between the different saving methods in Hibernate?
My suggetion:Always use saveOrUpdate //if record exists update otherwise new

Use session.merge(). Becuase, NonUniqueObjectException may be thrown when using Session.saveOrUpdate() in Hibernate - See more at: http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/#sthash.WJEbdSaG.dpuf

Related

Hibernate batch update issue

For a simple batch update of a MariaDB table, properly mapped as a Hibernate entity class, a simple update via Hibernate produces the error
org.hibernate.StaleStateException: Batch update returned unexpected row count from update
Each table record is modeled by an Entity class, which is a simple POJO that needs to be updated (if it already exists) or inserted as a new object (if it does not exist in the table), with a primary id field (not auto-incremented) and some other values, all scalar. The error can be reproduced by the following method.
public static void update(Set<Long> ids) {
Session session = createSession();
Transaction t = session.beginTransaction();
try {
for (Long id : ids) {
Entity entity = session.get(Entity.class, id);
if (entity == null) {
entity = new Entity();
}
entity.setId(id);
// Other entity value settings
session.saveOrUpdate(entity);
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
}
}
What is the correct way of implementing the above operation in Hibernate?
You are using saveOrUpdate() in this way Hibernate decides by his own logic what is a new (Transient) and what is an old (Persisted) object and depends on this performs save() or update() method accordingly.
Hibernate assumes that an instance is an unsaved transient instance if:
The identifier property is null.
The version or timestamp property (if it exists) is null.
A new instance of the same persistent class, created by Hibernate internally, has the same database identifier values as the given instance.
You supply an unsaved-value in the mapping document for the class, and the value of the identifier property matches. The unsaved-value attribute is also available for version and timestamp mapping elements.
Entity data with the same identifier value isn't in the second-level cache.
You supply an implementation or org.hibernate.Interceptor and return Boolean.TRUE from Interceptor.isUnsaved() after checking the instance in your code.
Otherwise: entity will be determined like already saved persisted
In your example, Hibernate did not determine the new (Transient) object and as result, perform update() method for it. It produced UPDATE instead of INSERT statement. UPDATE statement for not existing record returns zero updated records, so it is the reason for your exception.
Solution: explicitly use save() method for new entities:
public void update(Set<Long> ids) {
Session session = getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
try {
for (Long id : ids) {
HibernateEntity entity = session.get(HibernateEntity.class, id);
if (entity == null) {
entity = new HibernateEntity();
}
// Other entity value settings
entity.setValue(entity.getValue() + "modification");
if (entity.getId() == null) {
entity.setId(id);
session.save(entity);
}
}
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
}
}
update() method is not required to call explicitly. Transactional persistent instances (i.e. objects loaded, saved, created or queried by the Session) can be manipulated by the application, and any changes to persistent state will be persisted when the Session is flushed. According to documentation.

What will be the outcome if an entity object is accessed after transaction.commit() in Hibernate?

I am new to hibernate. I want to understand behavior once the transaction is commit. Consider below code-
Employee class is the class whose objects will be inserted/deleted to/from the database.
public static void main(String[] args) {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
long id = 2;
try {
session.beginTransaction();
Employee employee = (Employee) session.get(Employee.class, id);
session.delete(employee);
session.getTransaction().commit();
employee.getName(); /*What will happen at this line*/
}
catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
It becomes "Transient". From the Session class documentation
Persistent instances may be made transient by calling delete()
From the guide:
Transient - an object is transient if it has just been instantiated using the new operator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application does not hold a reference anymore. Use the Hibernate Session to make an object persistent (and let Hibernate take care of the SQL statements that need to be executed for this transition).
Take a look here for more info https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html

Data does not save while calling persist() multiple times

I am trying to persist to multiple entities. Sample code below:
public List<String> save(SalesInvoice salesInvoice, List<ClosingStock> closingStockList, Company company,
Receipt receipt) {
log.info("Saving Sales Invoice...");
if (salesInvoice.getSalesChallanId() == null) {
for (ClosingStock closingStock : closingStockList) {
if (existingClosingStock(closingStock.getProduct().getId().toString()) == null) {
em.persist(closingStock);
} else {
}
}
}
em.persist(salesInvoice);
receipt.setSalesInvoiceId(salesInvoice.getId());
em.persist(receipt);
return null;
}
// Edit: Add existingClosingStock method provided in comments
public ClosingStock existingClosingStock(String productId) {
try {
return (ClosingStock) em.createQuery("SELECT cv FROM ClosingStock cv WHERE cv.product.id=:productId") .setParameter("productId", productId).getSingleResult();
} catch (NoResultException e) {
return null;
}
}
Well, when I execute this query, the data didn't persist in database, but it shows the list of newly inserted data for small times, but data didn't save in database. I got no errors in console. Also put em.getTransaction().commit(); before return does not work. When I tried persisting on single entity and put em.getTransaction().commit();, it worked perfectly. Like this:
public void save(Location location) {
log.info("Saving Location.");
em.persist(location);
em.getTransaction().commit();
}
What did I miss here?
As explained in this article, persist just schedules an entity state transition. The insert is executed during flush. If you don't commit the transaction, the flush will not be triggered automatically.
Anyway, you should always start a transaction, even if you plan to read data.

Hibernate 5: Inserting Data

Currently, I am having this code to insert a Product object and it works totally fine!
public void insertProduct(Product product) {
Session session = this.databaseDriver.openSession();
Transaction transaction = session.beginTransaction();
session.save(product);
transaction.commit();
session.close();
}
However, this code does not seem to work:
public void insertProduct(Product product) {
Session session = this.databaseDriver.openSession();
session.save(product);
session.flush();
session.close();
}
What would be the reason for this? Neither does it give me any errors nor insert the data.
In hibernate even after calling session.flush it only updates an existing instance of the object not add a new one .Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory.

Making insertion in database using hibernate without making transaction instance

I have been making a simple program to save an employee details in mysql using hibernate framework as follows...
public class Manifest {
Session session;
public static void main(String[] args) {
Employee employee = new Employee("varun");
new Manifest().addEmployee(employee);
}
/* Method to CREATE an employee in the database */
public void addEmployee(Employee employee){
Integer employeeID=null;
SessionGenerator sessionGenerator = new SessionGenerator();
try{
session = sessionGenerator.getSessionToDb();
employeeID = (Integer) session.save(employee);
System.out.println(employeeId);
}catch (HibernateException e) {
e.printStackTrace();
}finally {
session.close();
}
}
}
I am aware of the fact that I should use session.beginTransaction(); & tx.commit() but my question is that why no exception is thrown here in my case and it is printing employeeId on console but not making any entry in database.. What the reason behind that???
1) Session.save() may perform an INSERT outside transaction boundaries: save() method returns an identifier, and if an INSERT has to be executed to get the identifier (e.g. "identity" generator), this INSERT happens immediately (in order to get an identity), no matter if you are inside or outside of a transaction.
2) Commit might happen even without transaction if you set:
<property name="connection.autocommit">true</property>
that's why an exception is not raised
Check this article (Working nontransactionally with Hibernate): https://developer.jboss.org/wiki/Non-transactionalDataAccessAndTheAuto-commitMode

Categories