indexed column treated like a PK

Description

I have a rather simple table:

CREATE TABLE ShopOrder(
shopOrderId MEDIUMINT AUTO_INCREMENT PRIMARY KEY,
......
shopperId MEDIUMINT,
INDEX(shopperId)
);

The JPA Entity is:

@Entity
@Table(name = "shoporder")
@Access(AccessType.FIELD)
@NamedQueries({
@NamedQuery(name = "ShopOrder.countOrdersByShopperId", query = "SELECT COUNT FROM ShopOrder s WHERE shopperId = :shopperId")})
public class ShopOrder implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer shopOrderId;
.....
@Column(name="shopperId")
private Integer shopperId;

//getters and setters
}

The code that throws the error:

@Stateless
public class ShopperFacade implements ShopperFacadeRemote {
@PersistenceContext(unitName="WebShopEJBPU")
EntityManager entityManager;

@Override
public int createOrder(int shopperId, String... args) {
ShopOrder shopOrder = new ShopOrder();
shopOrder.setAmount("0");
List<String> items = new ArrayList<String>();
for(int i = 1; i < args.length; i++)
items.add(args[i]);
shopOrder.setItems(items);
shopOrder.setShopperId(shopperId);
entityManager.persist(shopOrder);
entityManager.flush();

return shopOrder.getShopOrderId();
}

The error:
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: shop.entities.shopper.ShopOrder
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1215)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1148)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1154)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:678)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:269)
at shop.ejb.ShopperFacade.createOrder(ShopperFacade.java:121)
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.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5367)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
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 com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:862)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:371)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5339)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5327)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:206)
... 19 more
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: shop.entities.shopper.ShopOrder
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:672)
... 43 more

The problem does not occur if the line of code setting the shopperId is commented, as such:

@Override
public int createOrder(int shopperId, String... args) {
ShopOrder shopOrder = new ShopOrder();
shopOrder.setAmount("0");
List<String> items = new ArrayList<String>();
for(int i = 1; i < args.length; i++)
items.add(args[i]);
shopOrder.setItems(items);
//shopOrder.setShopperId(shopperId);
entityManager.persist(shopOrder);
entityManager.flush();

return shopOrder.getShopOrderId();
}

If I change the code as such:

ShopOrder shopOrder = new ShopOrder();
shopOrder.setAmount("0");
List<String> items = new ArrayList<String>();
for(int i = 1; i < args.length; i++)
items.add(args[i]);
shopOrder.setItems(items);
entityManager.persist(shopOrder);
entityManager.flush();
shopOrder.setShopperId(shopperId);
entityManager.merge(shopOrder);
entityManager.flush();

I get

javax.persistence.PersistenceException: org.hibernate.HibernateException: identifier of an instance of shop.entities.shopper.ShopOrder was altered from 11 to 12
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1215)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1148)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1154)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:798)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.flush(EntityManagerWrapper.java:418)
at shop.ejb.ShopperFacade.createOrder(ShopperFacade.java:125)
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.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5367)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
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 com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:862)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:801)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:371)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5339)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5327)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:206)
... 19 more
Caused by: org.hibernate.HibernateException: identifier of an instance of shop.entities.shopper.ShopOrder was altered from 11 to 12
at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:85)
at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:190)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:147)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:795)
... 43 more

It is as if the indexed column is treated like a PK

Environment

JPA 2.0 with hibernate as provider, Glassfish3.1, MySQL 5.1

Assignee

Unassigned

Reporter

Cristian Jujea

Labels

None

Feedback Requested

None

Feedback Requested By

None

backPortable

None

Suitable for new contributors

None

Pull Request

None

backportDecision

None

backportReEvaluate

None

Affects versions

Priority

Major
Configure