====== Exception Resolution Strategies ====== ===== Exception "LazyInitializationException" ===== ==== Exception ==== org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: *class name here*, no session or session was closed ==== Resolution ==== Use **attach()** to attach the fetched object to the current session. ==== Example ==== === Exception Present === def children = ne.children children.eachWithIndex { ne, index -> log.info ne.name } === No Exception Present === ne.attach() def children = ne.children children.eachWithIndex { ne, index -> log.info ne.name } \\ ===== Exceptions "StaleObjectStateException", "HibernateOptimisticLockingFailureException", "DuplicateKeyException" ===== ==== Exception Examples (Ticketer) ==== org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [*domainName*#*domain ID*] org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [com.errigal.ticketer.Ticket] with identifier [510111]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.errigal.ticketer.Ticket#510111] org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session: [com.errigal.ticketer.TicketStatus#591611]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.errigal.ticketer.TicketStatus#591611] ==== Resolution 1 ==== Use **attach()** to attach the fetched object to the current session. ==== Resolution 2 ==== Use **merge()** to attach the changes made to the object by different session/transaction to the current session object. ==== Resolution 3 ==== Fetch the required object ID before starting a new session and then create an new object inside the newly started session using its id, update the required values, and then save. ==== Resolution 3 Example (Ticketer, 'Alarm Clear Received' State) ==== arg , defaultArg , ticket -> Long ticketId = ticket.id com.errigal.ticketer.Ticket.withNewSession { sess -> def newTicket = com.errigal.ticketer.Ticket.get(ticketId) newTicket.dueDate = new Date() newTicket.priority = 1 as Integer newTicket.save() log.info "Set Due Date of Ticket ${newTicket.id} to be ${newTicket.dueDate} and Priority to ${newTicket.priority}." sess.flush() } log.info "Check: Ticket ${ticket.id} Due Date ${ticket.dueDate} and Priority ${ticket.priority}."