🔹 What happens technically:
When you call session.save(entity)
, Hibernate assigns an identifier (e.g., the primary key) and puts the entity into the session’s first-level cache — so it becomes persistent in the session context.
But if you haven’t started a transaction, then:
- There’s no active database transaction to guarantee that the pending insert will be executed and committed.
- Hibernate will still queue the SQL INSERT statement internally, but it won’t necessarily send it to the database immediately.
- If you close the session or an error happens before a transaction is committed, the entity’s changes may never actually get flushed to the database — leaving it effectively transient outside the session.
🔹 Example showing the problem:
Session session = sessionFactory.openSession(); // but NO transaction started!
User user = new User();
user.setUsername("john");
session.save(user); // Hibernate assigns ID, but no transaction active
// No commit happens, so changes might never be sent to DB!
session.close(); // Session closes → pending SQL is discarded → user is not saved in DB
🔹 Why doesn’t persist()
do this?
- The JPA
persist()
method requires an active transaction — if you try to callpersist()
outside a transaction, it throws aTransactionRequiredException
.
✅ This prevents you from accidentally thinking you saved something when no transaction is active.
🔹 Key takeaway:
save()
can mislead you into thinking you’ve persisted data when you haven’t committed a transaction → resulting in lost changes.- Always use
save()
(orpersist()
) inside an active transaction, and preferpersist()
for standard, safer behavior.