JPA 2.0 : Issue : orphanRemoval throwing integrity violations using Open JPA - java

Request assistance with the strange issue of cascade removal with JPA 2.0.Please find below the details
I'm using JPA bundled with IBM Websphere 8.5 that comes along with RAD.
The issue I'm facing is when I try deleting an entity having a one to Many relationships with another entity, I always encounter the ORA-02292: integrity constraint violation. Below are the specific parts highlighting the relationship between two entities - FeeForService and FeeForServiceProduct.
FeeForService has a One to Many Relationship with FeeForServiceProduct.
Please note the issue occurs when I run it on the Websphere server. I've tried running the below as a standalone program and it works with the workarounds of putting a cascade property at the many end and invoking em.remove() twice
#Entity
#Table(name="FEE_FOR_SERVICE")
public class FeeForService implements Serializable {
private static final long serialVersionUID = 1L;
....
....
//bi-directional many-to-one association to FeeForServiceProduct
#OneToMany(mappedBy="feeForService",cascade={CascadeType.ALL},orphanRemoval=true)
private Set<FeeForServiceProduct> feeForServiceProducts;
....
}
#Entity
#Table(name="FEE_FOR_SERVICE_PRODUCT")
public class FeeForServiceProduct implements Serializable {
....
....
//bi-directional many-to-one association to FeeForService
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name="FEE_FOR_SERVICE_ID")
private FeeForService feeForService;
}
Initially I had tried with only CASCADE=CASCADEType.ALL property but as it didn't work out had to use orphanRemoval.
The error that I receive is java.sql.SQLIntegrityConstraintViolationException: ORA-02292: integrity constraint violated. Child Record found.
Below is the code sample I have used for deleting the FFS entity, assuming by setting orphanRemoval to true I don't have to explicitly delete the FFSProduct entity. But that doesn't seem to be working
public void testDeleteFFS(){
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("DummyTestService");
EntityManager em=entityManagerFactory.createEntityManager();
long crVO=3658;
List<FeeForService> ffsExisting=(List<FeeForService>) em.createQuery("SELECT i FROM FeeForService i INNER JOIN i.customerRequest u where u.customerRequestId="+crVO).getResultList();
System.out.println("begin of delete");
//for deleting child entity FFSProduct
for(FeeForService ffsCandidate:ffsExisting){
em.getTransaction().begin();
em.remove(ffsCandidate);
em.getTransaction().commit();
}
/*for deleting parent entity FFS as the FFSProduct entity was retained when a single for loop was used*/
for(FeeForService ffsCandidate:ffsExisting){
em.getTransaction().begin();
em.remove(ffsCandidate);
em.getTransaction().commit();
}
System.out.println("End of delete");
}
Is there any way with JPA 2.0 where I can delete all the dependent entities by only invoking a remove operation on the parent entity and if so,please point out where I'm going wrong as my understanding until now is that this must be possible by setting orphanRemoval to true on the owning entity.
Also please note that the Cascade = CascadeType.ALL was given at the FFS product or the many end of the relationship as the solution was not working without it.(as I mentioned at the top it strangely seems to work when running as a standalone)
My persistence.xml properties are as below
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="DummyTestService" transaction-type="RESOURCE_LOCAL" >
<class>FeeForService</class>
<class>FeeForServiceProduct</class>
<validation-mode>NONE</validation-mode>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:oracle:thin:#xxxx"/>
<property name="openjpa.ConnectionDriverName" value="oracle.jdbc.OracleDriver"/>
<property name="openjpa.ConnectionUserName" value="xxxx"/>
<property name="openjpa.ConnectionPassword" value="xxxx"/>
<property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
<!-- <property name="openjpa.DynamicEnhancementAgent" value="true"/> -->
<property name="openjpa.Log" value="File=D:\XXXX\JPAstandalonelog,DefaultLevel=WARN, Tool=INFO,SQL=TRACE"/>
</properties>
</persistence-unit>
Thanks in Advance

Related

"Missing table" on materialized view

I have the following entity:
#Entity
#Table(name = "full_address")
public class FullAddress {
#Id
#Column(name = "guid")
private String id;
#Column(name = "address")
private String address;
//getters and setters omitted
}
Also I create materialized view as follows:
CREATE TABLE address_table (
-- address fields,
aoid VARCHAR(36),
CONSTRAINT address_pk PRIMARY KEY (aoid)
);
CREATE MATERIALIZED VIEW full_address AS
SELECT buildFullAddressById(addrobj.aoid) AS address, addrobj.aoid AS guid FROM address_table AS addrobj;
-- buildFullAddressById is an sql function which is not important here
When I launch Tomcat application, i always get
org.hibernate.HibernateException: Missing table: full_address
Why is this happening? How to fix it?
UPD: looks like a bug in hibernate: https://hibernate.atlassian.net/browse/HHH-9602
I have had the same bug for several past days. As this answer said, it is possible to disable hibernate.hbm2ddl.auto property in your persistence.xml, but it is not a good idea if your project is rapidly developing.
TL;DR: set property hibernate.hbm2dll.extra_physical_table_types to MATERIALIZED VIEW.
Or add -Dhibernate.hbm2dll.extra_physical_table_types="MATERIALIZED VIEW" to VM options. But it is better to such options to configuration file.
Right now, we are using PostgreSQL 9.6 and Hibernate 5.2.12.Final. Somewhy, all materialized views validations were failing with the following exception:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException:
Schema-validation: missing table [our_project_schema.mv_one_of_views]
All entities that successfully passed validation were either simple tables or views.
It seems like it is a default behaviour for generic databases. In sources here on lines 79-81 they add only these types:
final List<String> tableTypesList = new ArrayList<>();
tableTypesList.add( "TABLE" );
tableTypesList.add( "VIEW" );
Lines 85-87 tell us that there is a possibility to extend these hardcoded values with custom ones:
if ( extraPhysicalTableTypes != null ) {
Collections.addAll( tableTypesList, extraPhysicalTableTypes );
}
On line 56 it is declared private String[] extraPhysicalTableTypes;,
and on lines 71-77 there are some more values added into this array:
if ( !"".equals( extraPhysycalTableTypesConfig.trim() ) ) {
this.extraPhysicalTableTypes = StringHelper.splitTrimmingTokens(
",;",
extraPhysycalTableTypesConfig,
false
);
}
They come from lines 66-70, encoded as String under key EXTRA_PHYSICAL_TABLE_TYPES with empty default value:
final String extraPhysycalTableTypesConfig = configService.getSetting(
AvailableSettings.EXTRA_PHYSICAL_TABLE_TYPES,
StandardConverters.STRING,
""
);
And here on line 1545 is the declaration of that key:
/**
* Identifies a comma-separate list of values to specify extra table types,
* other than the default "TABLE" value, to recognize as defining a physical table
* by schema update, creation and validation.
*
* #since 5.0
*/
String EXTRA_PHYSICAL_TABLE_TYPES = "hibernate.hbm2dll.extra_physical_table_types";
So, adding this property will add another entry to tableTypesList that is used for filtering of many other entities in database, such as sequences, indices, temporary tables and others, that may have name similar to yours materialized view.
This is how my persistence.xml looks like, if you are interested:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="project-pu">
<jta-data-source>java:jboss/datasources/project-pu</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.hbm2dll.extra_physical_table_types" value="MATERIALIZED VIEW"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.use_sql_comments" value="false"/>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/mgt"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
</properties>
</persistence-unit>
</persistence>
P.S. I know it is a very old post, but I fought with this problem for a few days. I failed finding an answer, so I decided to put it somewhere in the Internet. And this somewhere became here. :)
It's definitely a bug of Hibernate and was described here: https://hibernate.atlassian.net/browse/HHH-9602
So, I recommend removing hibernate.hbm2ddl.auto property as a workaround.
I found out the most simple solution (assuming you still want to use Hibernate to validate the schema) is to add a subselect to the table definition.
Using hbm.xml
<hibernate-mapping>
<class name="com.initech.MvObject" table="MV_OBJ">
<!-- This is necessary when using older Hibernate versions because of
Hibernate bugs. See
https://hibernate.atlassian.net/browse/HHH-1329
https://hibernate.atlassian.net/browse/HHH-9602
-->
<subselect>select * from MV_OBJ</subselect>
Using annotations
import org.hibernate.annotations.Subselect;
import javax.persistence.Entity;
#Entity
#Subselect("select * from MV_OBJ")
public class MvObj{
}

Using #PersistenceContext and EntityManager for several schemas

I am currently working on a JavaSE project that I would like to build in the most effective way. My project is an employeeManagementSystem which has several schemas. For example I have one schema called employees which contains employee data and another schema called company which contains the company data.
Currently I have implemented my entities and tested these using hibernate.cfg.xml to make sure they are implemented correctly. For example, one such entity in the employee schema is
#Entity
#Table(name="employees", uniqueConstraints= {
#UniqueConstraint(columnNames="idEmployees"),
#UniqueConstraint(columnNames="idCardNumber"),
#UniqueConstraint(columnNames="niNumber")
})
public class Employee {
#Id
#GeneratedValue
#Column(unique=true, nullable=false, updatable=false)
private int idEmployees;
#Column(unique=true, nullable=false, updatable=false)
#Size(min=1, max=15)
private String idCardNumber;
#Column(unique=true, nullable=false, updatable=false)
#Size(min=1, max=15)
private String niNumber;
#Column(nullable=false, updatable=false)
#Size(min=1, max=20)
private String name;
#Column(nullable=false)
#Size(min=1, max=20)
private String surname;
// Other class variables
//Constructors
//getters & setters
}
I an now trying to use an EntityManager to manage my schemas. My persistence.xml for the employee schema is
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="EmployeesDAO" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.shopmanagementsystem.employeesdao.entities.Employee</class>
//Other classes in this schema
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/employees"/>
</properties>
</persistence-unit>
</persistence>
I want to create a Service and ServiceImpl class to manage the processes related to the entities.
Q1) Should I have a Service and ServiceImpl for each entity?
Some of my questions were answered already in a previous post JPA EntityManager Construction
Q2) I further asked about using #PersistenceContext and was kindly advised to ask another question with a more detailed description of my project.
I am happy to add more details if I've left anything out and thank you for your advice and help.
Q1) Should I have a Service and ServiceImpl for each entity?
Not necessarily. Based on the name of the persistence unit: EmployeesDAO, I'm assuming that Service and ServiceImp are intended to implement DAO pattern, right? In this context you have to offer a contract (INSERT / UPDATE/ DELETE / QUERY) just for those entities that actually require it. For example you can have a table called Category which has a relationship with Employee like this:
#Entity
#Table(name="categories")
public class Category implements Serializable {
...
#Id private BigInteger idCategory;
#Basic private String description;
...
}
#Entity
#Table(name="employees")
public class Employee implements Serializable {
...
#ManyToOne
#JoinColumn(name="idcategory", referencedColumnName="idcategory")
private Category category;
...
}
In this example you would have a Service to manage Category entities only if you need to. If those entities are managed by another application then you just need to have read privileges on categories table so the entity manager can map this data and that's it.
Q2) I further asked about using #PersistenceContext and was kindly advised to ask another question with a more detailed description of my
project.
First of all please beware that #PersistenceContext annotation is intended to be used with container-based persistence, as part of a Java EE application. You cannot use this annotation in plain Java SE platform.
On the other hand it doesn't mean you can't use JPA. Yes, it's perfectly possible, but you have to take care of the whole entity managers life-cycle. It is a common practice in this case to implement design patterns (such as Abstract Factory or Factory method or Singleton) in order to instantiate/access your entity managers manually.
In addition if you want to develop the top level layers of your application using Java SE and use container-managed persistence, then you can code the persistence layer using JPA and Enterprise JavaBeans architecture. This approach is not simple but has several advantages:
You can offer the persistence layer as a service through EJB modules.
Database connections and pools can be managed by the EJB container. This is extremely useful to separate database connection info from persistence.xml file.
As already mentioned, the EJB container will manage the whole entity manager life-cycle.
You can go further and leave container use Java Transaction API so you can forget (more or less) about transactional stuff.
Other comments
I know that posted persistence.xml is probably just an example but I have to mention that connect to the database as root user is not a good practice at all. Due to security reasons you should have several users with the right privileges to access your database, and likely none of them will ever need super-user privileges.
Finally, applications design is a really broad topic and it can be simple or complex based on your requirements. In addition there are several frameworks/technologies that can be used and is very very easy to get lost if you don't have any experience. My suggestion if you never did something like this before is to start with a very basic application and then go further.

Can I generate JPA entities with EAGER fetchType by default?

Im using JPA persistence.xml and generating my entities with the Hibernate code generator. My persistence.xml looks like this:
<persistence-unit name="my_schema">
... classes ...
<properties>
<property name="hibernate.connection.url" value="jdbc:mysql://10.12.200.101:3306/my_schema"></property>
<property name="hibernate.default_catalog" value="my_schema" />
<property name="hibernate.connection.username" value="my_user"></property>
<property name="hibernate.connection.password" value="my_pass"></property>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"></property>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"></property>
<property name="hibernate.connection.nombre" value="my_schema" />
</properties>
</persistence-unit>
All my entities are generated with the FetchType.LAZY by default:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "entity_name")
Is there a way to generate this entities with FetchType.EAGER by default?
All #ManytoOne and #OneToOne relationships are EAGER by default.
The #OneToMany associations are LAZY for a very good reason.
Assuming you have a root entity:
Country, having a one-to-many association states
each State has a one-to-many association cities
each City has a one-to-many association streets
each Street has a one-to-many association HouseNumbers
If you have the default option of fetching all these one-to-many associations eagerly, it could be that selection one Country will end up fetching the whole database.
This is a major performance concern and you should plan your fetching strategy responsively.
If all your one-to-many associations are fetched eagerly, and one parent entity (Parent) has 2 unrelated one-to-many associations (children and jobs) then fetching the parent entity will end up in a Cartesian Product of all the one-to-many associations.
So, in conclusion:
plan your fetch strategy carefully
rely less on the default `EAGER fetching
explicitly use fetch joins in all JPQL or Criteria API queries to extract the right amount of info you need for a certain job

JPA persist fails for GenerationType.IDENTITY

I have an old application that worked fine in JBOss 5, JPA and Derby. I am now porting it to JBoss 6, only to find that system is unable to insert the entity with error message:
Column 'ID' cannot accept a NULL value.
Where, ID is an identity column:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
int id;
...
}
I checked the generated schema and it looks good:
CREATE TABLE "APP"."CUSTOMER" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"EMAIL" VARCHAR(255),
"NAME" VARCHAR(255),
"PHONE" VARCHAR(255));
You can look at the code of the application in the link below. Any help is appreciated.
https://docs.google.com/open?id=0B_lXBrNTL1s-R3NHb2hYZlJ1Znc
Raj
Well, I got things to work. Basically, when you use JPA to generate the schema in Derby, it creates the tables just fine, but then has problem inserting rows with identity column. The solution was not to generate schema from JPA. I manually created the schema and commented out the schema generation option.
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ContactsPU" transaction-type="JTA">
<jta-data-source>java:DerbyDS</jta-data-source>
<class>com.webage.contacts.Customer</class>
<!--
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
-->
</persistence-unit>
</persistence>
You can fix this without having to create the scheme yourself.
Simply change from GenerationType.IDENTITY to GenerationType.TABLE.
#GeneratedValue(strategy=GenerationType.TABLE)
I was having the same problem in derby and this solved it.

org.hibernate.ObjectNotFoundException: No row with the given identifier exists, but it DOES

I've got a hibernate problem that I can't fix.
The setup: Java EE, web app, Hibernate 3.2, Tomcat 6, Struts 2.
Basically, I persist an object with my server logic (a struts action), then try and pull that data out for the next page and display it.
I check the database after I save the object, and sure enough, I can see the row there with all the data.
But when I try and retrieve it I get this:
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [msc.model.Picture#73]
To make things even muddier, when I restart Tomcat and try and access the same object, I don't get the error - Hibernate finds the row just fine.
Hibernate will also be able to see the row if I do some other operations - maybe add a row here and there to the database, not even on the same table.
From all this I suspect a Hibernate bug, but I'm a Hibernate newbie so I am probably wrong. Please help! I've googled and googled to no avail.
Here is my Hibernate config:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/msc</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">-------</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">80</property>
<property name="current_session_context_class">thread</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<mapping resource="msc/model/Picture.hbm.xml"/>
<mapping resource="msc/model/Comment.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Here are my two mapping files:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="msc.model.Picture" table="PICTURE">
<id column="PICTURE_ID" name="id">
<generator class="native"/>
</id>
<property name="story"/>
<property name="email"/>
<property name="category"/>
<property name="state"/>
<property name="ratings"/>
<property name="views"/>
<property name="timestamp"/>
<property name="title"/>
<property lazy="true" name="image" type="blob">
<column name="IMAGE"/>
</property>
<property lazy="true" name="refinedImage" type="blob">
<column name="REFINEDIMAGE"/>
</property>
<property lazy="true" name="thumbnail" type="blob">
<column name="THUMBNAIL"/>
</property>
<bag cascade="save-update" lazy="true" name="comments" table="COMMENT">
<key column="PICTURE"/>
<one-to-many class="msc.model.Comment"/>
</bag>
</class>
</hibernate-mapping>
and
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="msc.model.User" table="USER">
<id column="USER_ID" name="id">
<generator class="native"/>
</id>
<property name="username"/>
<property name="email"/>
<bag cascade="save-update" lazy="true" name="pictures" table="PICTURE">
<key column="USER"/>
<one-to-many class="msc.model.Picture"/>
</bag>
<bag cascade="save-update" lazy="true" name="comments" table="COMMENT">
<key column="USER"/>
<one-to-many class="msc.model.Comment"/>
</bag>
</class>
</hibernate-mapping>
Please let me know if you need more info, I'm happy to oblige.
(note: this is not a duplicate of this question, the scenario is not the same "No row with the given identifier exists" although it DOES exist)
EDIT: as requested, posting Java code:
Code to save object
Session hib_ses = HibernateUtil.getSessionFactory().getCurrentSession();
hib_ses.beginTransaction();
hib_ses.save(user);
hib_ses.getTransaction().commit();
Code to display data (an image in this case)
public class ImageAction extends ActionSupport implements ServletResponseAware, SessionAware {
private HttpServletResponse response;
Map session;
private Long id;
private int thumbnail;
private InputStream inputStream;
#Override
public String execute() throws Exception {
response.setContentType("image/jpeg");
Session hib_session = HibernateUtil.getSessionFactory().getCurrentSession();
hib_session.beginTransaction();
//what is the ID now?
Picture pic = (Picture) hib_session.load(Picture.class, getId());
if (thumbnail == 1) {
inputStream = (ByteArrayInputStream) pic.getThumbnail().getBinaryStream();
} else {
inputStream = (ByteArrayInputStream) pic.getRefinedImage().getBinaryStream();
}
hib_session.close();
return SUCCESS;
}
This happens because you have inserted something which is meant to be a foreign key but do not reference anything.
Check out you database whether that key exist or not(even though it is in database in other tables).
Check all your mappings and database settings. It may be possible you are setting some not-null="true" in foreign key relations when your database says nullable="true". The first causes an INNER JOIN and the second causes LEFT JOIN.
Set log level to TRACE to see all steps and look for generated SQL when retrieving the objects.
In many to one relationship you need to tell Hibernate what needs to be done if the mapped row is not found. You can configure it in the following ways:
Annotation:
#NotFound(action = NotFoundAction.IGNORE)
Mapping XML:
<many-to-one name="user" column="user_id" class="com.xyz.User" cascade="save-update, evict" not-found="ignore"/>
Just check your database whether id 73 is available or not in your particular table
Okay, I am going to throw out a theory here. Could it be that you are trying to load the picture the first time before the transaction has been committed?
Since the transaction is not yet committed, the row is not visible to the transaction you are using for reading the picture (depends on what transaction isolation level you have).
Then, since hib_session.close() is not inside a finally block, it will not be executed, and the thread-bound session will still have an open transaction. The subsequent request gets the same Hibernate session, with the same open transaction, and you get the same result from the select it issues (again, dependent on transaction isolation level - see documentation here, in particular for REPEATABLE_READ).
This could also explain why flush() makes it slightly better, because if the flush() occurs earlier than the commit(), there's a smaller chance for the race condition to occur.
I suggest you try closing the session in a finally block and see if the behavior changes for subsequent requests.
I Faced this issue and here is What happened and How i resolved it. You most probably have the same thing going on too.
I had POST and USER objects. They are in a OneToMany relationship(A user can have many posts). Making it bidirectional they are in a ManyToOne relationship too (one post belongs to only one user).
Post class looks
#Entity
#Table(name="Post")
public class Post {
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
private long postId;
private String title;
private String body;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "postUserId")
private AutoUser autoUser;
// getter and setters
User class is
#Entity
#Table(name = "AUTO_USER")
public class AutoUser implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long autoUserId;
#Column(name = "USERNAME")
private String username;
#OneToMany
private List<Post> postList = new ArrayList<>();
// getter and setters
The first table names were Post and AUTO_USER I had 3 users persisted to a AUTO_USER table(with id 1, 2, 3).. And 3 entry to the Post table 1 for each user.
(the join columns or foreign key were 1, 2, 3)
Then I changed only the table name for the user object only and named it #Table(name = "AUTO_USER2").
and I had only one user in this table with id 1.
In my code I iterate over each post and identify which post belongs to which user and display them those belonging to the current logged in user.
After changing the post table name I got this exception
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#2
Which is telling me that the user object with id 2 is not available in the new user Table.
then I registered one more user with id 2 and later I got this
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#3
This time it could not find user with id 3
Finally registered a third user and had not exception.
As you can see, the foreign key exists in the post table but since I changed the user table, there could not be a match for them and that is the reason I was facing this issue.
To avoid that situation I created new table names for both objects and started fresh
Hope this will help
I don't see any real problems pertaining to the exception in the code, you might wanna try:
Checking that the transaction is flushed or calling flush() manually after committing;
Checking whether the ID is passed to load() and whether the right ID is passed to it via debugger
Enabling Hibernate to print the generated SQL and/or enabling logging
I have a similar problem with hibernate 3.6.10, while I'm just searching and selecting (if exist).
Annotation:
#Entity
public class Familiares {
#OneToMany(mappedBy = "familiares")
private List<FamiliaresBaja> bajas;
#Entity
#Table(name = "familiares_baja")
public class FamiliaresBaja implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#JoinColumn(name = "familiares_id")
#ManyToOne(optional = false)
private Familiares familiares;
then i retrieve a List and with these looking in FamiliaresBaja if there is at least one.
createQuery("from FamiliaresBaja where familiares.id="+ id).uniqueResult() // should return a single result or null not throw a Exception
This must be a Hibernate bug
Please check the value of lower_case_table_names of your mysql server. If its value is 0, check the SQL generated by hibernate, make sure the table name's case is consistent with the actual table name in mysql.
Check triggers, if you have a before insert trigger, and having NEXTVAL in the sequence, cause that error.
You may have a one-to-one relationship in the entity you are looking for with a different ID, try to load the entity with the ID in the mapped table rather then the identity column.
The correct way to solve this problem is to use session.get() method. Get method will return null if entity is not found.
Caused by: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.emmanuel.Entity.Classe#17]
at org.hibernate.boot.internal.StandardEntityNotFoundDelegate.handleEntityNotFound(StandardEntityNotFoundDelegate.java:28)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:216)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:327)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118)
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1215)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1080)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:697)
at org.hibernate.type.EntityType.resolve(EntityType.java:464)
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)
at org.hibernate.engine.internal.TwoPhaseLoad$EntityResolver.lambda$static$0(TwoPhaseLoad.java:576)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntityEntryLoadedState(TwoPhaseLoad.java:221)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:155)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:126)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1201)
at org.hibernate.loader.Loader.processResultSet(Loader.java:1009)
at org.hibernate.loader.Loader.doQuery(Loader.java:967)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:357)
at org.hibernate.loader.Loader.doList(Loader.java:2868)
at org.hibernate.loader.Loader.doList(Loader.java:2850)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2682)
at org.hibernate.loader.Loader.list(Loader.java:2677)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1906)
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:370)
I had this same problem, I had previously deleted an object which was referenced in another table and when I loaded the objects I had a foreign key in the table which did not refer to anything hence this exception.
[com.emmanuel.Entity.Classe#17] specifies that the object which is referenced with id 17 in the table whose objects I want to load does not exist.
My issue was that the child in the relation had a FK which didn't map to the PK of the parent so I had to change the JoinColumn to include referencedColumnName
#Entity
#Table(name = "child")
class Child {
#ManyToOne
#JoinColumn(name = "child_id", referencedColumnName = "non_pk_parent_id")
var iabCategory: IabCategory
}
Note that this caused another issue because of a bug in Hibernate. Here's a stackoverflow post on it:
Jpa Repository got error cannot not serializable when get data from database
and the link to the Hibernate bug: https://hibernate.atlassian.net/browse/HHH-7668
This bug forced me to mark the parent Serializable
#Entity
#Table(name = "parent")
class Parent : Serializable {
}
The bug would cause a ClassCastException to be thrown if the parent didn't implement Serializable

Categories

Resources