IllegalStateException LogicalConnectionManagedImpl is closed Hibernate - java

I'm using H2 Database with hibernate on JAVA and I'm getting a weird error.
I have created my abstract repository to manage the basic CRUD operation.
The exception I am getting is this:
java.lang.IllegalStateException: org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl#d20d74a is closed
at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.errorIfClosed(AbstractLogicalConnectionImplementor.java:37)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:135)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:254)
at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.rollback(AbstractLogicalConnectionImplementor.java:116)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.rollback(JdbcResourceLocalTransactionCoordinatorImpl.java:294)
at org.hibernate.engine.transaction.internal.TransactionImpl.rollback(TransactionImpl.java:139)
at repositories.AbstractRepository.save(AbstractRepository.java:32)
at services.ResultService.saveResult(ResultService.java:76)
at services.API.WebRequestService.run(WebRequestService.java:124)
at services.API.ThreadService.run(ThreadService.java:67)
AbstractRepository save method:
public <T> T save(T t) {
Transaction transaction = null;
try (Session session = HibernateConfig.getSessionFactory().openSession()) {
transaction = session.beginTransaction();
Serializable entityId = session.save(t);
transaction.commit();
T createdEntity = (T) session.get(t.getClass(), entityId);
return createdEntity;
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
}
return null;
}
I am a CS student and I am not very much familiar with Hibernate. I'm not getting this error on my computer, only on other computers with the JAR file builded.
P.S English isn't my main language so I am very sorry if you don't understand me clearly!

After hours of debugging I found the error!
The error was that a column exceeded the length and the exception was coming from the catch block.
The catch block was trying to rollback something that its connection was already closed.
I hope this will be helpful to someone!

I got the same error when trying to create an embedded relationship between two tables using Hibernate version 5.5.3. Yes the above answer was helpful for me to debug the error in a single go. Thanks to #William. It was same in my case too, the catch block was trying to rollback the transaction due to an exception occurred in the Embeddable class. The issue was that I did not have a default constructor inside Embeddable class.
Thanks!

#Vikarm's answer and #William's answer pointed me to the right direction. You simply need to create your composite ID in the constructor of the class that has the EmbeddedId.
Here's how it looks like in code (full example is included for completeness purposes)
#Entity(name = "artwork_rating")
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
public class ArtworkRating {
#EmbeddedId
private ArtworkRatingKey id; // This needs to be instantiated*
private int score;
private String content;
// --------- Relations --------- //
#ManyToOne
#MapsId("userId")
#JoinColumn(name = "user_id")
User user;
#ManyToOne
#MapsId("artworkId")
#JoinColumn(name = "artwork_id")
Artwork artwork;
// --------- Constructors --------- //
public ArtworkRating(int score, String content, User user, Artwork artwork) {
this.id = new ArtworkRatingKey(user.getId(), artwork.getId()); // *as shown here
this.score = score;
this.content = content;
this.user = user;
this.artwork = artwork;
}
}

Related

JPA-Repository save: Proceed saving after insert Constraint violation

i'm using JPA repository to save simple data objects to the database. To avoid duplicates i created a unique constraint on multiple fields. If now a duplicate according to the unique fields/constraint should be saved i want to catch the exception, log the object and the application should proceed and saves the next object. But here i always get this exception: "org.hibernate.AssertionFailure: null id in de.test.PeopleDBO entry (don't flush the Session after an exception occurs)".
In general i understand what hibernate is doing, but how i can revert the session or start a new session to proceed with saving of the next data objects. Please have a look to the code below:
PeopleDBO.java
#Entity
#Data
#Table(
name = "PEOPLE",
uniqueConstraints = {#UniqueConstraint(columnNames = {"firstname", "lastname"}})
public class PeopleDBO {
public PeopleDBO(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
}
The Test:
public void should_save_people_and_ignore_constraint_violation(){
final List<PeopleDBO> peopleList = Arrays.asList(
new PeopleDBO("Georg","Smith"),
new PeopleDBO("Georg","Smith"),
new PeopleDBO("Paul","Smith")
);
peopleList.forEach(p -> {
try {
peopleRepository.save(p);
} catch (DataIntegrityViolationException e) {
log.error("Could not save due to constraint violation: {}",p);
}
}
Assertions.assertThat(peopleRepository.count()).isEqualTo(2);
}
The problem is, that with saving of the second people the unique constraint gets violated. The error log happens, and with the next call of peopleRepository.save() the mentioned exception above is thrown:
"org.hibernate.AssertionFailure: null id in de.test.PeopleDBO entry (don't flush the Session after an exception occurs)"
How i can avoid this behaviour? How i can clean the session or start a new session?
Thanks a lot in advance
d.
--------- Edit / new idea ------
I just tried some things and have seen that i could implement a PeopleRepositoryImpl, like this:
#Service
public class PeopleRepositoryImpl {
final private PeopleRepository peopleRepository;
public PeopleRepositoryImpl(PeopleRepository peopleRepository) {
this.peopleRepository = peopleRepository;
}
#Transactional
public PeopleDBO save(PeopleDBO people){
return peopleRepository.save(people);
}
}
This is working pretty fine in my tests. ... what do you think?
One single transaction
The reason is that all inserts occur in one transaction. As this transaction is atomic, it either succeeds entirely or fails, there is nothing in-between.
The most clean solution is to check if a People exists before trying to insert it:
public interface PeopleRespository {
boolean existsByLastnameAndFirstname(String lastname, String firstname);
}
and then:
if (!peopleRepository.existsByLastnameAndFirstname(p.getLastname, p.getFirstname)) {
peopleRepository.save(p);
}
One transaction per people
An alternative is indeed to start a new transaction for each person. But I am not sure it will be more efficient, because there is an extra cost to create transaction.

JPA #ManyToOne #JoinFormula throwing ClassCastException

I'm trying to model a many-to-one bi-directional association using JPA. The join uses a formula. I've tried it a couple of ways, as shown below. Once with just JoinFormula and another with JoinColumnsOrFormulas.
public class JobOperation
{
private Operation operation;
#ManyToOne
// #JoinFormula("CASE WHEN attribute7 IS NULL OR TO_NUMBER(attribute7) = 0 THEN standard_operation_id ELSE TO_NUMBER(attribute7) END")
#JoinColumnsOrFormulas(
{
#JoinColumnOrFormula(formula = #JoinFormula(//
value = "(CASE WHEN this_.attribute7 IS NULL OR TO_NUMBER(this_.attribute7) = 0 THEN this_.standard_operation_id ELSE TO_NUMBER(this_.attribute7) END)", //
referencedColumnName = "standard_operation_id"))
})
#Fetch(FetchMode.SELECT)
#NotFound(action = NotFoundAction.IGNORE)
public Operation getOperation()
{
return this.operation;
}
}
I originally was using Hibernate 4.3.9 and then tried with Hibernate 5.1.0. Both throw the same exception:
15:55:21,408 DEBUG [org.hibernate.cfg.annotations.TableBinder] Retrieving property com.icumed.ifactory3.dto.wip.JobOperation.operation
15:55:21,409 DEBUG [org.hibernate.jpa.HibernatePersistenceProvider] Unable to build entity manager factory
java.lang.ClassCastException: org.hibernate.mapping.Formula cannot be cast to org.hibernate.mapping.Column
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:584)
Nothing in Hibernate's TableBinder class refers to a formula. Does Hibernate just not support this or am I using the wrong annotations, or is there something else going on?
The root cause of the problem seems to be on the other side of the association. I originally had this
public class Operation extends AbstractOperation
{
#OneToMany(mappedBy="operation")
public Set<JobOperation> getJobOperations()
{
return this.jobOperations;
}
}
and when I changed it to the following, it worked.
public class Operation extends AbstractOperation
{
#OneToMany
#JoinColumn(name="STANDARD_OPERATION_ID")
public Set<JobOperation> getJobOperations()
{
return this.jobOperations;
}
}

Java persistence - No parrent key found after flushing

I have two entity object that represent two database table.
There is a foreign key relationship beetween two fields in the tables..
I am try to create a new instance from one entity and persist, then try to create another and pass the first object to the secound object as paramter in the set...() method.
But it throws Constraint violation exception because parent key not found in the database then the transaction rolled back.
BPackage newCond = new BPackage();
newCond.setName(condomName);
//...
//...
try {
em.persist(newCond);
em.flush();
} catch (ConstraintViolationException e) {
LOG.warning(e.getMessage());
return null;
}
BAssocPackage newRel = new BAssocPackage();
newRel.setPackageId(newCond); //here try to pass..
//...
//...
try {
em.persist(newRel);
} catch (ConstraintViolationException e) {
LOG.warning(e.getMessage());
return null;
}
My EntityManager is container managed so I can't close it.
#Stateless
public class MainDataAccess implements MainDataAccessLocal {
#PersistenceContext(unitName = "WarmHomeColl-ejbPU")
private EntityManager em;
There is lot of properties in my entity classes, so i will not post all of them but this is my first entity:
public class BPackage implements Serializable {
//...
//...
#OneToMany(mappedBy = "packageId")
private Collection<BAssocPackage> bAssocPackageCollection;
//...
//..
public class BAssocPackage implements Serializable {
//...
//...
#JoinColumn(name = "PACKAGE_ID", referencedColumnName = "ID")
#ManyToOne
private BPackage packageId;
//...
//..
Please help me. :) Thank you!
Solved it.
There was a trigger on the id field in the database and i wasn't refereed to a right id.. when i deleted the trigger from the field it start working fine..

hibernate findbyid causes update?

I faced with a very strange behavior in my web app with spring 3 and hibernate-core 3.5.1-Final.
For simplicity i provide my code..
if(ripid!=null){ //Parameter
Appuntamento apDaRip = appuntamentoService.findById(ripid);
if(apDaRip.getIdpadre()!=null){
apDaRip.setNota("RIPROGRAMMATO n."+ripid.toString()+"\n"+apDaRip.getNota());
apDaRip.setIdpadre(apDaRip.getIdpadre());
}else{
apDaRip.setNota("RIPROGRAMMATO n."+ripid.toString()+"\n"+apDaRip.getNota());
apDaRip.setIdpadre(ripid);
}
try{
apDaRip.setOrarioinizio(null);
apDaRip.setDurata(null);
//apDaRip.setIdappuntamento(null);
}catch(Exception e){e.printStackTrace();}
map.put("appuntamento", apDaRip);
}
di = datiintranetService.findById(DatiintranetService.PASS_X_INTERVENTI);
map.put("passinterventi", di.getBoolean());
The idea behind is to use some data of an object "Appuntamento" for produce a new one.
So i'm going to change some value and before send the object to my view (jsp) i fetch other data by calling findbyid. This cause an update to the Appuntamento object... Off course i don't want this behavior. Someone can have an explanation of this?
Edit-1
Here's the Dao
#Transactional
public class DatiintranetService {
private DatiintranetDAO datiintranetDAO;
public void setDatiintranetDAO(DatiintranetDAO datiintranetDAO) {
this.datiintranetDAO = datiintranetDAO;
}
public DatiintranetDAO getDatiintranetDAO() {
return datiintranetDAO;
}
public Datiintranet findById(Integer id) {
return datiintranetDAO.findById(id);
}
}
and For Appuntamento class I provide to you a snapshot
#Entity
#Table(name = "appuntamento", schema = "public")
public class Appuntamento implements java.io.Serializable {
#Id
#SequenceGenerator(name="appuntamentoID", sequenceName="appuntamento_idappuntamento_seq",allocationSize =1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="appuntamentoID")
#Column(name = "idappuntamento", unique = true, nullable = false)
public Integer getIdappuntamento() {
return this.idappuntamento;
}
}
Edit-2
IF i move thoese two row above the if statement no update occur.
di = datiintranetService.findById(DatiintranetService.PASS_X_INTERVENTI);
map.put("passinterventi", di.getBoolean());
If you query for an entity and change the entity, the default behavior is to persist those changes via an update to the database. This is usually what you want to happen, but obviously not in all cases.
If you want to avoid the update, you need to detach the entity by calling session.evict(apDaRip) where session is a reference to the hibernate session (see Session.evict()). You probably want to evict the entity right after you get it (immediately following the call to findById).

AppEngine datastore: "Object with id ... is managed by a different Object Manager"

I'm using the Google AppEngine, with Java. When I use some datastore features, I'm getting an error message:
Object with id "edvaltt.Teacher#64064b" is managed by a different Object Manager
I don't know what this means or how to fix it or where to look for documentation on this error. Can anyone help me? The code I'm using is:
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class School {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private String shortname;
#Persistent
private String fullname;
#Persistent
#Order(extensions = #Extension(vendorName="datanucleus", key="list-ordering", value="code asc"))
private List<Teacher> Teachers;
...
public Teacher FindOrCreateTeacher(String code)
{
// Can we find the teacher without any database code?
Teacher newTeacher = FindTeacher(code);
if (newTeacher != null)
return newTeacher;
// Create the teacher:
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
for (Teacher teacher : Teachers) {
if (teacher.getCode() == code) {
tx.rollback();
return teacher;
}
}
newTeacher = new Teacher(code);
Teachers.add(newTeacher);
pm.makePersistent(newTeacher);
pm.makePersistent(Teachers);
tx.commit();
} finally {
tx.commit();
}
return newTeacher;
}
I believe that "private List<Teacher> Teachers;" refers to an "owned, one to many" relationship.
A persistent object can only be "managed" by one PersistenceManager. In DataNucleus this is backed internally by an "ObjectManager". The message says that you are trying to associate an object managed by one PM with a different PM. You can easily debug that by printing out the PM for each (persistent) object
JDOHelper.getPersistenceManager(obj);
Since you don't define where the message comes from, not much more can be said. The DataNucleus log entries would tell you way way more than that.
Closing the PM is always an essential thing to do (unless you want resource leaks)
As illustrated in this ticket, shouldn't you close the pm (PersistenceManager)?
} finally {
tx.commit();
pm.close();
}
DataNucleus,
Thank you for the pm.close(); tip.
I was making a query with one em
em = EMF.get().createEntityManager();
and making a commit with another one without closing the first one.

Categories

Resources