【发布时间】:2015-12-17 11:33:40
【问题描述】:
我正在为我的应用程序使用休眠。有时休眠会生成重复的 ID,而我使用的策略是增量,它从表中执行 max(ID) 并添加一个。我不知道它为什么会发生并且它突然发生,之后对该表插入操作的所有后续请求都失败了。解决方法是重新启动 tomact 服务器。
这里是申请详情
1. 部署在 liferay-tomcat.each 上的 3 个应用程序都有自己的 abstraction-impls.jar。这个 JAR 包含使用 Hibernate 与 oracle 交互的类。我可能怀疑这是导致此问题的一种可能情况。
2.所有3个应用程序都有休眠相关的JAR
我做了以下测试,确认问题是否是由于多线程导致的, 1) 创建了 3 个线程,每个线程运行一个 for 循环 20 次以插入同一个表> 我没有发现任何问题。一切顺利。
这是上面的示例代码。
public class ThreadTest implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<20;i++){
UserManagement userManagement = new UserManagementImpl(-1);
Context context = new Context();
context.setUserId("testUser");
context.getUserContextMap().put("password", "shiva123");
try{
int sessionId = userManagement.login(context);
System.out.println("thread<<"+Thread.currentThread().getName() + ">> "+sessionId);
}catch(Exception e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new ThreadTest());
Thread t2 = new Thread(new ThreadTest());
Thread t3 = new Thread(new ThreadTest());
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
问题是如何获得正确的 ID 或如何避免生成重复的 ID?
这是给我带来问题的代码。
下面是hibernate映射类。
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@javax.persistence.Entity
@Table(name="entities",
uniqueConstraints = {@UniqueConstraint(columnNames={"id"})})
@org.hibernate.annotations.GenericGenerator(
name = "test-increment-strategy",
strategy = "increment")
public class EntityImpl extends Entity {
/**
* Serial Version UID for this class
*/
private static final long serialVersionUID = -9214466697134157251L;
@Override
public String toString() {
return "EntityImpl [entityId=" + entityId + ", entityName="
+ entityName + ", entityType=" + entityType
+ ", parentEntityId=" + parentEntityId + ", entityHierarchy="
+ entityHierarchy + "]";
}
private int entityId;
private String entityName;
private String entityType;
private int parentEntityId;
private String entityHierarchy;
@Id
@GeneratedValue(generator = "test-increment-strategy")
@Column(name = "ID", nullable = false, updatable = false)
public int getEntityId() {
return entityId;
}
/** Sets the Entity ID for this instance */
public void setEntityId(int entityId) {
this.entityId = entityId;
}
/** Retrieves the name of this Entity instance */
@Column(name = "entity_name", nullable = false)
public String getEntityName() {
return entityName;
}
/** Sets the name of this Entity instance */
public void setEntityName(String entityName) {
this.entityName = entityName;
}
/** Retrieves the type of this Entity instance */
@Column(name = "entity_type", nullable = false, updatable = false)
public String getEntityType() {
return entityType;
}
/** Sets the type of this Entity instance */
public void setEntityType(String entityType) {
this.entityType = entityType;
}
/** Retrieves the Parent Entity ID for this instance */
@Column(name = "parent_id")
public int getParentEntityId() {
return parentEntityId;
}
/** Sets the Parent Entity ID for this instance */
public void setParentEntityId(int parentEntityId) {
this.parentEntityId = parentEntityId;
}
@Column(name = "ENTITY_HIERARCHY", nullable = false, updatable = false)
public String getEntityHierarchy() {
return entityHierarchy;
}
public void setEntityHierarchy(String entityHierarchy) {
this.entityHierarchy = entityHierarchy;
}
}
以下是实体的保存方法
private boolean save (Serializable object, Session session) throws EntityNotFoundException, InternalSystemException {
logger.debug("save() - start");
Transaction tx = null;
boolean successful = false;
boolean localInit = false;
try {
if (session == null) {
session = createSession();
tx = session.beginTransaction();
//session.save(object);
localInit = true;
}
session.save(object);
logger.debug("**********************************");
logger.debug("object: "+object);
logger.debug("**********************************");
if (localInit == true) {
tx.commit();
}
successful = true;
} catch(HibernateException ex) {
logger.error("error in saving entity "+ ex);
if (localInit == true && tx !=null)
tx.rollback();
ex.printStackTrace();
throw new InternalSystemException("error in saving entity "+ ex);
} catch(Exception ex) {
logger.error("error in saving entity "+ex);
if (localInit == true && tx !=null)
tx.rollback();
new InternalSystemException("error in saving entity "+ ex);
}finally {
if (localInit && session != null) {
session.flush();
session.clear();
session.close();
}
}
if (logger.isDebugEnabled()) {
logger.debug("save() - end");
}
return successful;
}
错误不会一直发生,但一旦发生,同样会继续,测试的oracle环境是Oracle RACK。
【问题讨论】:
-
你有 3 个不同的 webapps,每个都插入到同一个表中,使用增量策略?
-
是的.. 有 3 个 Web 应用程序和相同的 JAR,每个都插入到同一个表中,然后复制到每个 Web 应用程序的 lib 文件夹中。他们使用增量策略。即使我也尝试过使用序列。但问题仍然存在。
标签: hibernate session tomcat liferay