derby + hibernate ConstraintViolationException using manytomany relationships - java

I'm new to Hibernate+Derby... I've seen this issue mentioned throughout the google, but have not seen a proper resolution.
This following code works fine with mysql, but when I try this on derby i get exceptions:
( each Tag has two sets of files and vise-versa - manytomany)
Tags.java
#Entity
#Table(name="TAGS")
public class Tags implements Serializable
{
#Id #GeneratedValue(strategy=GenerationType.AUTO)
public long getId()
{
return id;
}
#ManyToMany(targetEntity=Files.class
)
#ForeignKey(name="USER_TAGS_FILES",inverseName="USER_FILES_TAGS")
#JoinTable(name="USERTAGS_FILES",
joinColumns=#JoinColumn(name="TAGS_ID"),
inverseJoinColumns=#JoinColumn(name="FILES_ID"))
public Set<data.Files> getUserFiles()
{
return userFiles;
}
#ManyToMany(mappedBy="autoTags",
targetEntity=data.Files.class)
public Set<data.Files> getAutoFiles()
{
return autoFiles;
}
Files.java
#Entity
#Table(name="FILES")
public class Files implements Serializable
{
#Id #GeneratedValue(strategy=GenerationType.AUTO)
public long getId()
{
return id;
}
#ManyToMany(mappedBy="userFiles",
targetEntity=data.Tags.class)
public Set getUserTags()
{
return userTags;
}
#ManyToMany(targetEntity=Tags.class
)
#ForeignKey(name="AUTO_FILES_TAGS",inverseName="AUTO_TAGS_FILES")
#JoinTable(name="AUTOTAGS_FILES",
joinColumns=#JoinColumn(name="FILES_ID"),
inverseJoinColumns=#JoinColumn(name="TAGS_ID"))
public Set getAutoTags()
{
return autoTags;
}
I add some data to the DB, but when running over Derby these exception turn up (the don't using mysql)
Exceptions
SEVERE: DELETE on table 'FILES' caused a violation of foreign key constraint 'USER_FILES_TAGS' for key (3). The statement has been rolled back.
Jun 10, 2010 9:49:52 AM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: could not delete: [data.Files#3]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2712)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2895)
at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:97)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:260)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:613)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:344)
at $Proxy13.flush(Unknown Source)
at data.HibernateORM.removeFile(HibernateORM.java:285)
at data.DataImp.removeFile(DataImp.java:195)
at booting.DemoBootForTestUntilTestClassesExist.main(DemoBootForTestUntilTestClassesExist.java:62)
I have never used derby before so maybe there is something crutal that i'm missing
1) what am I doing wrong?
2) is there any way of cascading properly when I have 2 many-to-many relationships between two classes?
Thanks!

This following code works fine with MySQL, but when I try this on derby I get exceptions:
My guess is that you weren't using referential integrity with MySQL (i.e. not the InnoDB engine) so the constraint violation wasn't "triggered". But the error is there.
And actually, the problem is that you should put the mappedBy on the same side of the bi-directional associations, for example on Tags for both ManyToMany (and remove it from Files):
#Entity
public class Tags implements Serializable {
#ManyToMany(mappedBy = "userTags")
#ForeignKey(name = "USER_TAGS_FILES", inverseName = "USER_FILES_TAGS")
#JoinTable(name = "USERTAGS_FILES", joinColumns = #JoinColumn(name = "TAGS_ID"), inverseJoinColumns = #JoinColumn(name = "FILES_ID"))
public Set<Files> getUserFiles() {
return userFiles;
}
#ManyToMany(mappedBy = "autoTags")
public Set<Files> getAutoFiles() {
return autoFiles;
}
//...
}
And Files becomes:
#Entity
public class Files implements Serializable {
#ManyToMany
public Set<Tags> getUserTags() {
return userTags;
}
#ManyToMany
#ForeignKey(name = "AUTO_FILES_TAGS", inverseName = "AUTO_TAGS_FILES")
#JoinTable(name = "AUTOTAGS_FILES", joinColumns = #JoinColumn(name = "FILES_ID"), inverseJoinColumns = #JoinColumn(name = "TAGS_ID"))
public Set<Tags> getAutoTags() {
return autoTags;
}
// ...
}
With these changes, the following test passes (the session is created outside the test method):
#Test
public void removeFiles() {
Files files = (Files) session.get(Files.class, 1L);
session.delete(files);
session.flush();
Query q = session.createQuery("from Files f where f.id = :id");
q.setParameter("id", 1l);
Files result = (Files) q.uniqueResult();
assertNull(result);
}
And generates the following queries:
Hibernate: select files0_.id as id100_0_ from Files files0_ where files0_.id=?
Hibernate: delete from AUTOTAGS_FILES where FILES_ID=?
Hibernate: delete from Files_TAGS where userFiles_id=?
Hibernate: delete from Files where id=?
Hibernate: select files0_.id as id100_ from Files files0_ where files0_.id=?
Tested with Derby.

Related

How to configure Entity class for MySQL database table witch has n:m relationship and multiple primary keys

When I run the spring boot project I get the following error
" Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity:"
I have a few other classes with multiple primary keys and foreign keys but they didn't run to an error.
import javax.persistence.*;
#Entity
#Table(name="roles_has_features")
public class RoleFeatures {
#Column(name = "role_id_fk")
private Long roleIdFk;
#Column(name = "feature_id_fk")
private Long featureIdFk;
public Long getRoleIdFk() { return roleIdFk; }
public void setRoleIdFk(Long roleIdFk) { this.roleIdFk = roleIdFk; }
public Long getFeatureIdFk() { return featureIdFk; }
public void setFeatureIdFk(Long featureIdFk) { this.featureIdFk = featureIdFk; }
}
This actually has nothing to do with Spring. This is an error thrown by Hibernate, because JPA specification requires an Identity for each entity. As for your case, I would not suggest to create a separate entity, because as far as I understand from your column names, it's just a mapping for a relation between role and feature tables. I'd suggest to JPA Many-To-Many relationship. Take a look at #ManyToMany and #JoinTable annotations.
Also this looks as a really good tutorial for me
Hibernate – Many-to-Many example
The error message describes the issue pretty well:
No identifier specified for entity
You do not have an #Id annotated column in your RoleFeatures entity. Thus, hibernate is unable to identify an entity in the database and refuses to start.
Your so-called entity looks more like an Many-To-Many relationship. Maybe it's better to go this way.
Something like this:
#Entity
public class Role {
#Id
#Column(name = "role_id")
private Long id;
#ManyToMany
#JoinTable(name = "roles_has_features",
joinColumns = #JoinColumn(name = "feature_id_fk", referencedColumnName = "feature_id"),
inverseJoinColumns = #JoinColumn(name = "role_id_fk", referencedColumnName = "role_id"))
private List<Feature> features;
...
}
See also: https://www.baeldung.com/jpa-many-to-many

Hibernate deletes occurring out of order

I have the following classes:
Category
#Entity
#Table(name = "category", schema = "customer")
public class Category extends CustomerOwned {
...
}
CatalogueItem
#Entity
#Table(name = "catalogue_item", schema = "customer")
#EntityListeners(value = { CatalogueItemStatusListener.class })
public class CatalogueItem extends CatalogueOwned implements Statusable<CatalogueItem, CatalogueItemStatus> {
...
#OneToMany(mappedBy = "catalogueItem", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<CatalogueItemCategory> categories;
...
}
CatalogueItemCategory
#Entity
#Table(name = "catalogue_item_category", schema = "customer")
public class CatalogueItemCategory extends CatalogueItemOwned implements CategoryOwner {
...
#ManyToOne
#JoinColumn(name = "category_id", nullable = false, insertable = true, updatable = false)
private Category category;
...
}
We perform very few hard deletes in our application, but Categorys are hard deleted. CatalogueItemCategorys are also hard deleted.
I'm creating a service to allow someone to delete a Category and at the same time I check all Category dependencies and delete those too, so I'm doing this:
#Transactional
public DependentItemsResultResource delete(String categoryId, boolean force) {
List<CatalogueItem> catalogueItems = catalogueItemRepository.getByCategory(getCustomerStringId(), categoryId);
DependentItemsResultResource resultResource = new DependentItemsResultResource();
resultResource.setDependentCatalogueItems(new SearchResponse().from(catalogueItems, CatalogueItemSummaryResource::new));
if (!catalogueItems.isEmpty()) {
if (!force) {
resultResource.setDeleted(false);
return resultResource;
}
catalogueItems.forEach(item -> {
item.getCategories().removeIf(catalogueItemCategory -> categoryId.equals(catalogueItemCategory.getCategory().getStringId()));
sendEvent(prepareEvent(new CatalogueItemUpdatedEvent(), item.getCatalogue().getStringId(), item.getStringId()));
});
}
Category category = getCategory(categoryId);
resultResource.setDeleted(true);
categoryRepository.delete(category);
CategoryDeletedEvent event = new CategoryDeletedEvent();
event.setCategoryPath(category.getPath());
sendEvent(prepareEvent(event, categoryId));
return resultResource;
}
This is causing the following exception:
Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FKLYKUEHJG9UL0LR36O5XDD3MLF: CUSTOMER.CATALOGUE_ITEM_CATEGORY FOREIGN KEY(CATEGORY_ID) REFERENCES CUSTOMER.CATEGORY(ID) (1)"; SQL statement:
delete from customer.category where id=? [23503-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:426)
at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:443)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:318)
at org.h2.table.Table.fireConstraints(Table.java:967)
at org.h2.table.Table.fireAfterRow(Table.java:985)
at org.h2.command.dml.Delete.update(Delete.java:101)
at org.h2.command.CommandContainer.update(CommandContainer.java:98)
at org.h2.command.Command.executeUpdate(Command.java:258)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:160)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:146)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 109 common frames omitted
I've tried replacing this bit:
item.getCategories().removeIf(catalogueItemCategory -> categoryId.equals(catalogueItemCategory.getCategory().getStringId()));
with this:
item.getCategories().stream()
.filter(catalogueItemCategory -> categoryId.equals(catalogueItemCategory.getCategory().getStringId()))
.forEach(catalogueItemCategoryRepository::delete);
but it's not making any difference. Hibernate is deleting the objects out of order. It should be deleting the CatalogueItemCategory objects before the Category objects, but it's not.
How do I get it to delete in the correct order?
Edit: missed this class which provides the parent of the CatalogueItemCategory:
#MappedSuperclass
public class CatalogueItemOwned extends Updateable {
...
#ManyToOne
#JoinColumn(name = "catalogue_item_id", nullable = false, insertable = true)
private CatalogueItem catalogueItem;
...
}
There are dirty solutions, that are both anti-pattern, but would probably work:
Either use a flush after each delete, or delete with a native query.
That said, I recommend not to use any of these solutions, but to search for a cleaner solution.
I've solved this by explicitly deleting the category and all dependencies as follows:
#Transactional
public DependentItemsResultResource delete(String categoryId, boolean force) {
List<CatalogueItem> catalogueItems = catalogueItemRepository.getByCategory(getCustomerStringId(), categoryId);
DependentItemsResultResource resultResource = new DependentItemsResultResource();
resultResource.setDependentCatalogueItems(new SearchResponse().from(catalogueItems, CatalogueItemSummaryResource::new));
if (!catalogueItems.isEmpty()) {
if (!force) {
resultResource.setDeleted(false);
return resultResource;
}
catalogueItems.forEach(item -> sendEvent(prepareEvent(
new CatalogueItemUpdatedEvent(), item.getCatalogue().getStringId(), item.getStringId())));
}
Category category = getCategory(categoryId);
resultResource.setDeleted(true);
categoryRepository.deleteCatalogueItemCategoriesByCategory(category);
categoryRepository.deleteCategory(category);
CategoryDeletedEvent event = new CategoryDeletedEvent();
event.setCategoryPath(category.getPath());
sendEvent(prepareEvent(event, categoryId));
return resultResource;
}
The repo methods are:
#Modifying
#Query("delete from Category c where c = :category")
void deleteCategory(#Param("category") Category category);
and
#Modifying
#Query("delete from CatalogueItemCategory where category = :category")
void deleteCatalogueItemCategoriesByCategory(#Param("category") Category category);
Not the best, but also not the worst. Not using native deletes and it's still within the main transaction.

PK not found while saving collection of entities (bug ??)

i have ORA-02291 while creating new object (entitymanager.persist(taskVisit))
#Entity(name = "CRM_TASKDEPARTURE")
#Access(AccessType.PROPERTY)
#DiscriminatorValue(value = TaskType.Consts.VISIT_ID)
public class TaskVisit extends Task {
private static final long serialVersionUID = 1L;
private List<TaskVisitAddress> addresses = new ArrayList();
public TaskVisit() { }
#OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.PERSIST,mappedBy = "taskVisit")
public List<TaskVisitAddress> getAddresses() {
return addresses;
}
}
Connstraint is CRM_TaskVisitAddress(TASKID)
Code of entity:
#Entity(name = "CRM_TaskDepartureAddress")
public class TaskVisitAddress implements Serializable {
...any fields
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "TASKID")
public TaskVisit getTaskVisit() {
return taskVisit;
}
#Id
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PERSONADDRESSID")
public PersonAddress getPersonAddress() {
return personAddress;
}
}
Exception:
Error Code: 2291
Call: INSERT INTO CRM_TASKDEPARTUREADDRESS (TASKID, PERSONADDRESSID) VALUES (?, ?)
bind => [3299, 1]
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (DUMMY.FK_CRM_TASKDEPARTUREADDR_TASKI) violated - parent key not found
Where is the mistake?
P.s. in test object saved without exception...
Updated
I found wrong INSERT generated sequence
1. insert into superclass Task (right)
2. insert into CRM_TaskDepartureAddress (wrong)
3. insert into CRM_TASKDEPARTURE (wrong)
№ 2 and 3 must be swaped, becouse CRM_TaskDepartureAddress referenced to CRM_TASKDEPARTURE .
Updated
InheritanceType.JOINED
You cannot have a ManyToOne as your primary key; it is stating that there are many TaskVisitAddress instances referencing the same TaskVisit, while your #Id requires something that is unique.
You need to find something on your TaskVisitAddress that will uniquely identify it from other TaskVisitAddress instances, such as Integer id assigned through sequencing.
The #JoinColumn(name = "TASKID") is referring to "TASKID" in the Task table, as JPA only allows relationships to reference an Entity's primary key, making the constraint requiring CRM_TASKDEPARTURE to be inserted first is incorrect. If you must keep the constraint and require CRM_TASKDEPARTURE to be inserted first, you can try specifying the table name in the joinColumn:
#JoinColumn(name = "TASKID", referencedColumnName = "CRM_TASKDEPARTURE.TASKID")
as described in feature request
https://bugs.eclipse.org/bugs/show_bug.cgi?id=333100

Can one-to-one shared primary key mapping in Hibernate be optional/null?

I have seen quite a few examples/tutorials on the web for doing one-one shared primary key mapping using Hibernate annotations. However in all the examples that I have seen it seems the mapping can't be optional or if it is optional it can't be on the primary key. I have the following situation where I have a one-one primary key mapping between a Company table
and a CompanyDocs table. The CompanyDocs table is a weak entity, i.e although a Company object exists, it necessarily won't have a CompanyDocs entity linked from the start, however this may be created later on.
The Company object are created and persisted by an external application, however updated using the Hibernate application.
This is what I have..(Please note this is not the actual example)
Company table
- companyid (Pk)
- name
- desc
- test1
- test2
CompanyDocs table
- docsid (Pk) (Fk)
- detail1
- detail2
- detail3
Model Classes
Company.java
#Entity
#Table(name = "company", schema = "public")
public class Company implements java.io.Serializable {
private String companyid
private CompanyDocs companydocs;
#Id
#Column(name = "companyid", unique = true, nullable = false, length = 20)
public String getCompanyid() {
return this.companyid;
}
public void setCompanyid(String companyid) {
this.companyid = companyid;
}
#OneToOne(fetch = FetchType.LAZY, mappedBy = "companydocs")
#NotFound(action = NotFoundAction.IGNORE)
#PrimaryKeyJoinColumn(name = "companyid", referencedColumnName = "docsid")
public CompanyDocs getCompanydocs() {
return this.companydocs;
}
public void setCompanydocs(CompanyDocs companydocs) {
this.companydocs = companydocs;
}
}
CompanyDocs.java
#Entity
#Table(name = "companydocs", schema = "public")
public class CompanyDocs implements java.io.Serializable {
private String docsid;
private Company company;
#GenericGenerator(name = "generator", strategy = "foreign", parameters =
#Parameter(name = "property", value = "company"))
#Id
#GeneratedValue(generator = "generator")
#Column(name = "docsid", unique = true, nullable = false, length = 20)
public String getDocsid() {
return this.docsid;
}
public void setDocsid(String docsid) {
this.docsid = docsid;
}
#PrimaryKeyJoinColumn(name = "docsid", referencedColumnName = "companyid")
#OneToOne(fetch = FetchType.LAZY)
#NotFound(action = NotFoundAction.IGNORE)
public Company getCompany() {
return this.company;
}
public void setCompany(Company company) {
this.company = company;
}
CompanyDAOImpl.java
public Company getCompany(String companyid) {
Criteria c = sessionFactory.getCurrentSession().createCriteria(Company.class)
.add(Restrictions.eq("companyid", companyid));
try {
return (Company) c.list().get(0);
}
catch(IndexOutOfBoundsException e) {
logger.info("GetCompany threw exception " +e);
return null;
}
}
public void storeCompany(Company c) {
sessionFactory.getCurrentSession().saveOrUpdate(c);
}
public void storeCompanyDocs(CompanyDocs cd) {
sessionFactory.getCurrentSession().saveOrUpdate(cd);
}
public CompanyDocs getCompanyDocs(String companyid) {
try{
Criteria c = sessionFactory.getCurrentSession()
.createCriteria(CompanyDocs.class).add(Restrictions.eq("companyid", companyid));
logger.info("getCompanyDocsreturned"+c.list().get(0));
return (CompanyDocs)c.list().get(0);
}catch(IndexOutOfBoundsException e){
logger.info("getCompanyDocs threw exception " +e);
return null;
}
}
CompanyServiceImpl.java
#Transactional(propagation = Propagation.REQUIRED, readOnly= false,
noRollbackFor=IllegalArgumentException.class)
#ExceptionHandler(NullPointerException.class)
public CompanyResponse updateCompany(Service parameters) throws SOAPException {
LOG.info("In updateCompany");
Company c = companyDao.getCompany(parameters.getId());
//CompanyDocs cd = companyDao.getCompanyDocs(parameters.getId());
CompanyDocs cd = c.getCompanyDocs();
LOG.info("CompanyDocs object is:- " + cd);
if(cd == null)
{
cd = new CompanyDocs(parameters.getId());
c.setCompanyDocs(cd);
cd.setCompany(c);
LOG.info("CompanyDocs object created new :- " + cd);
companyDao.storeCompanyDocs(cd);
LOG.info("CompanyDocs object stored :- " + cd.getDocsid());
}
c.setDetail1();
c.setDetail2();
c.setDetail3();
.............
companyDao.storeCompany(c)
LOG.info("Stored Company");
LOG.info("CompanyService Response Return------:")
return new CompanyResponse();
}
My log file prints this.
2012-05-02 22:57:18,951 INFO [au.com.CompanyServiceImpl] - <In updateCompany>
2012-05-02 22:57:18,975 INFO [au.com.CompanyDAOImpl] - <getCompany returned
au.com.Company#2738ef1d>[au.com.CompanyServiceImpl] - <CompanyDocs object is:- null>
2012-05-02 22:57:18,991 INFO [au.com.CompanyServiceImpl] - <CompanyDocs object
created new :- au.com.CompanyDocs#373ee92>
2012-05-02 22:57:18,995 INFO [au.com.CompanyServiceImpl] - <CompanyDocs object
updated :- CO12345>
2012-05-02 22:57:19,338 INFO [au.com.CompanyDAOImpl] - <Stored Company >
2012-05-02 22:57:19,338 INFO [au.com.CompanyServiceImpl] - <CompanyService
Response Return------:>
2012-05-02 22:57:19,498 ERROR [org.hibernate.jdbc.AbstractBatcher] - <Exception
executing batch: >
org.hibernate.StaleStateException: Batch update returned unexpected row count from
update [0]; actual row count: 0; expected: 1 at
org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
at
org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:68)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at org.hibernate.event.def.AbstractFlushingEventListener
.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.
onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.springframework.orm.hibernate3.HibernateTransactionManager.
doCommit(HibernateTransactionManager.java:656)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.
processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager
.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport
.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor
.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation
.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.
invoke(JdkDynamicAopProxy.java:202)
at $Proxy28.login(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.
invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.cxf.service.invoker.AbstractInvoker.
performInvocation(AbstractInvoker.java:173)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:89)
at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:60)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:75)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.
run(ServiceInvokerInterceptor.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at org.apache.cxf.workqueue.SynchronousExecutor.
execute(SynchronousExecutor.java:37)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.
handleMessage(ServiceInvokerInterceptor.java:106)
at org.apache.cxf.phase.PhaseInterceptorChain.
doIntercept(PhaseInterceptorChain.java:255)
at org.apache.cxf.transport.ChainInitiationObserver.
onMessage(ChainInitiationObserver.java:113)
at org.apache.cxf.transport.servlet.ServletDestination.
invoke(ServletDestination.java:97)
at org.apache.cxf.transport.servlet.ServletController.
invokeDestination(ServletController.java:461)
at org.apache.cxf.transport.servlet.ServletController.
invoke(ServletController.java:188)
at org.apache.cxf.transport.servlet.AbstractCXFServlet.
invoke(AbstractCXFServlet.java:148)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.
handleRequest(AbstractHTTPServlet.java:179)
at org.apache.cxf.transport.servlet.
AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:103)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.
service(AbstractHTTPServlet.java:159)
at org.apache.catalina.core.ApplicationFilterChain.
internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.
doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.
invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.
invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.
invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.
process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
2012-05-02 22:57:19,501
ERROR [org.hibernate.event.def.AbstractFlushingEventListener]
- <Could not synchronize database state with session>
I have tried using #non annotation,optional = false/true, also tried using a uni-directional mapping and loading the companydocs object using criteria. But it seems Hibernate always excepts a CompanyDocs object for an existing Company..
Strangely enough, this is used to work fine, when we were working with an earlier version of hibernate and were using mapping files , instead of annotaions. It was a shared key mapping but unidirectional so the Company hbm file had no mapping of CompanyDocs object.
I am using hibernate 3.3.1.GA.jar for annotations. Is there something I have done wrong on my side or is this not possible anymore with the new version of Hibernate?
The problem was Hibernate was issuing an update , instead of an insert command for the companydocs object. This is because if the primary key for the object is null then Hibernate will do inserts, if it is not null it will do an update and in my case as I was setting the key in the implementation class as below, it was doing an update.
Original Code
if(cd == null)
{
cd = new CompanyDocs(parameters.getId());
c.setCompanyDocs(cd);
cd.setCompany(c);
LOG.info("CompanyDocs object created new :- " + cd);
companyDao.storeCompanyDocs(cd);
LOG.info("CompanyDocs object stored :- " + cd.getDocsid());
}
New Code
if(cd == null)
{
cd = new CompanyDocs();//no-arg constructor
c.setCompanyDocs(cd);
cd.setCompany(c);
LOG.info("CompanyDocs object created new :- " + cd);
companyDao.storeCompanyDocs(cd);
LOG.info("CompanyDocs object stored :- " + cd.getDocsid());
}
Worked beautifully !!
I found this link useful for fixing this issue
Hibernate StaleStateException
#PrimaryKeyJoinColumn should only be used in the optional side , so remove #PrimaryKeyJoinColumn that is annotated on the Company.
Besides , mappedBy attribute of the #OneToOne should refer to the property name of the entity that #OneToOne is marked on. So it should be :
#OneToOne(fetch = FetchType.LAZY, mappedBy = "company")

java.lang.ClassCastException: org.hibernate.action.DelayedPostInsertIdentifier cannot be cast to java.lang.Long

used: hibernate 3.6.2, maven 2, postgres 9.
I have code that must work but it doesn't. When I launch functional test I've got the error:
java.lang.ClassCastException: org.hibernate.action.DelayedPostInsertIdentifier cannot be cast to java.lang.Long
Code is a standart domain model:
Entity:
#Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
#Entity
#Table(schema = "simulators", name = "mySimulator_card")
public class MySimulatorCard {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "account_number", unique = true, nullable = false)
private String accountNumber;
etc...
DAO:
public abstract class AbstractDao<E, PK extends Serializable> implements Dao<E, PK> {
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
#PersistenceContext(unitName = "MySimulator")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public abstract Class<E> getEntityClass();
#Override
public void persist(E e) {
getEntityManager().persist(e);
}
#Override
public E merge(E e) {
return getEntityManager().merge(e);
}
#Override
public void refresh(E e) {
getEntityManager().refresh(e); //<-- some thing wroooong
}
#Override
public void delete(E e) {
getEntityManager().remove(e);
}
etc...
And according table:
CREATE TABLE simulators.mySimulator_card
(
id bigserial NOT NULL,
account_number character varying(255) NOT NULL,
etc...
CONSTRAINT mySimulator_card_pk PRIMARY KEY (id),
CONSTRAINT mySimulator_card_account_fk FOREIGN KEY (account_id)
REFERENCES simulators.mySimulator_account (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT mySimulator_card_currency_fk FOREIGN KEY (currency_id)
REFERENCES simulators.mySimulator_currency ("name") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT mySimulator_card_product_fk FOREIGN KEY (product_id)
REFERENCES simulators.mySimulator_product (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT mySimulator_account_account_number_uq UNIQUE (account_number),
CONSTRAINT mySimulator_card_san_uq UNIQUE (san)
)
WITH (
OIDS=FALSE
);
ALTER TABLE simulators.mySimulator_card OWNER TO functional;
Here are stack trace till my code:
at org.hibernate.type.descriptor.java.LongTypeDescriptor.unwrap(LongTypeDescriptor.java:36)
at org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$1.doBind(BigIntTypeDescriptor.java:52)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:91)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:282)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:277)
at org.hibernate.loader.Loader.bindPositionalParameters(Loader.java:1873)
at org.hibernate.loader.Loader.bindParameterValues(Loader.java:1844)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1716)
at org.hibernate.loader.Loader.doQuery(Loader.java:801)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2037)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:86)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:76)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3293)
at org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:151)
at org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:62)
at org.hibernate.impl.SessionImpl.fireRefresh(SessionImpl.java:1118)
at org.hibernate.impl.SessionImpl.refresh(SessionImpl.java:1098)
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:738)
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:713)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
at $Proxy153.refresh(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy82.refresh(Unknown Source)
at com.goooogle.simulator.mysimulator.dao.AbstractDao.refresh(AbstractDao.java:42)
Why? Is it hibernate's bug?
I had faced exactly same exception when doing a save(). I solved it by correcting the cascade option in the hibernate mapping file. I changed it from "all-delete-orphan,save-update, delete "to "save-update, delete, delete-orphan" and it worked for me.
Hope it helps.
This exception baffled me just today and happened in a Spring Boot application using the JpaRepository.
In my case this occured when a JpaRepostitory.findBySomeEntity was called. SomeEntity had been saved in the same transaction using JpaRepository.save(...) rather than JpaRepository.saveAndFlush(...). Therefore its ID was not yet set.
Looks like Hibernate is trying to substitute the missing entity id with the DelayedPostInsertIdentifier created in the uncommitted save-transaction even though it can't be cast to the id-type.
It's a misleading Exception. Good thing it was easily fixed by the saveAndFlush(...).
Is your driver and dialect correct in your hibernate.properties file?
hibernate.connection.driver_class = org.postgresql.Driver
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html_single/#configuration-hibernatejdbc
You didn't define your primary key as IDENTITY on your create table statement.
id bigserial NOT NULL IDENTITY
I understand that the question was asked pretty while ago, but there is no answer for my case and I had to deal it myself.
So in my case the issue was in Parent-child Entity relations, I defined non-nullable join column as #JoinColumn(nullable = false) and Hibernate could not insert child Entity without knowing parent ID. Throwing me java.lang.ClassCastException: class org.hibernate.action.internal.DelayedPostInsertIdentifier cannot be cast to class java.lang.Long.
So the fix was in setting #JoinColumn as nullable.
My parent Entity was:
#Entity
public class Quiz {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
#JoinColumn(name = "quiz_id", nullable = false)
#OneToMany(orphanRemoval = true, cascade = CascadeType.ALL, targetEntity = Question.class)
#Fetch(FetchMode.JOIN)
public List<Question> questionList;
}
And my child Entity was:
#Entity
public class Question {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
}
And the fixed Parent Entity:
#Entity
public class Quiz {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
#JoinColumn(name = "quiz_id")
#OneToMany(orphanRemoval = true, cascade = CascadeType.ALL, targetEntity = Question.class)
#Fetch(FetchMode.JOIN)
public List<Question> questionList;
}
Logically I understand that this was my fault, since it's not possible to insert non-nullable ID when you don't know it, but Hibernate could thrown better, not so confusing, exception.
And yes, after the fix Hibernate issues additional Entity update to set parent ID:
DEBUG [org.hib.SQL] insert into Quiz (user_name) values ($1) returning id
DEBUG [org.hib.SQL] insert into Question (question) values ($1) returning id
DEBUG [org.hib.SQL] update Question set quiz_id=$1 where id=$2

Categories

Resources