【问题标题】:Hibernate: How to fix “identifier of an instance altered from A to B”?Hibernate:如何修复“实例的标识符从 A 更改为 B”?
【发布时间】:2015-08-28 05:05:02
【问题描述】:

org.hibernate.HibernateException: 实例标识符 org.com.Pricing 从 241 更改为 242

我遇到了这个异常。我有一个名为应用程序的实体,它映射到应用程序表。当应用程序同时被持久化时,一些默认值应该被持久化到另一个名为 Pricing 的表中。

该项目是一个动态的网络项目,有一定数量的用户可以登录。并且任何用户都可以创建一个应用程序,当他们点击 sav 时,实体应该被保存在数据库中。

当单个用户进行保存时,它工作正常......但是当 3-4 个用户尝试同时保存时,它会抛出上述异常。正在创建应用程序,但在保持定价时出现上述异常。

我们使用带有 Spring 集成的 Hibernate 4,并且 Hibernate 模板用于事务。 有什么办法可以解决这个问题。

@Transactional

public class ApplicationDao extends BaseDao {

         private Application application = null;
/**
 * Bean Injection Start
 * @param applicationDTO
 * @return
 */
public void setApplication(Application application) {
    this.application = application;
}
/**
 * End
 */

@SuppressWarnings("unchecked")
public int persistApplication(ApplicationDTO applicationDTO){

    String appName = null;

    int appId = -1;
    Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();

    Query query = session.createQuery("from Application app where app.APP_NAME=:APP_NAME and app.OWNER_ID=:OWNER_ID");

    query.setParameter("APP_NAME", applicationDTO.getAPP_NAME());

    List<Application> applicationList = query.list();
    for(Application application : applicationList){
        appName = application.getAPP_NAME();
    }
    if(appName ==null || appName ==""){
        appName = "NO_DATA";
    }
    if(appName.equalsIgnoreCase(applicationDTO.getPP_NAME())){
        System.out.println("app Name Already Exist");
        appId = -1;
    }
    else
    {

    try{
         BeanUtils.copyProperties(application, applicationDTO);
         appId=application.getAPP_ID();
     }catch(ConversionException coversionExc){

         coversionExc.printStackTrace();
     }catch(IllegalAccessException illegalAccessExce){

         illegalAccessExce.printStackTrace();
     }catch(InvocationTargetException invocationTargetExce){

         invocationTargetExce.printStackTrace();
     }
    saveOrUpdate(application);
    appId=application.getAPP_ID();
    System.out.println("app id "+appId);
    }
    return appId;
}
    public class BaseDao extends HibernateDaoSupport {

protected void saveOrUpdate(Object entity) {
    getHibernateTemplate().saveOrUpdate(entity);
    getHibernateTemplate().flush();
    }

protected HibernateTemplate getTemplate() {
    return getHibernateTemplate();
    }
}




@Entity
 public class Application{


@Id
@GenericGenerator(name="generator", strategy="increment")
@GeneratedValue(generator="generator")
private int APP_ID;

@Column
private String APP_NAME;

public int getAPP_ID() {
    return APP_ID;
}

public void setAPP_ID(int aPP_ID) {
    APP_ID = aPP_ID;
}

public String getAPP_NAME() {
    return APP_NAME;
}

public void setAPP_NAME(String aPP_NAME) {
    APP_NAME = aPP_NAME;
}

}

@Entity
public class Pricing {


@Id
@GenericGenerator(name="generator", strategy="increment")
@GeneratedValue(generator="generator")
private int Pricing_ID;

@Column
private int APP_ID;

@Column
private double PRICE;

public int getAPP_ID() {
    return APP_ID;
}

public void setAPP_ID(int aPP_ID) {
    APP_ID = aPP_ID;
}

public int getPricing_ID() {
    return Pricing_ID;
}

public void setPricing_ID(int pricing_ID) {
    Pricing_ID = pricing_ID;
}

public double getPRICE() {
    return PRICE;
}

public void setPRICE(double pRICE) {
    PRICE = pRICE;
}

}

以下是Application Context xml文件中的内容。

    <property name="dataSource" ref="mySQLDBConnectionDetails"></property>

    <property name="annotatedClasses">
        <list>
            <value>org.com.Application</value>
            <value>org.com.Pricing</value>
        </list>
    </property>

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>
<tx:annotation-driven proxy-target-class="true"
    transaction-manager="transactionManager" />

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="mysessionFactory" />
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
    <property name="sessionFactory" ref="mysessionFactory" />
</bean>

如果需要任何信息,也会提供该信息...提前致谢。

【问题讨论】:

标签: java spring hibernate


【解决方案1】:
     BeanUtils.copyProperties(application, applicationDTO);
     appId=application.getAPP_ID();

在这里,您从 DTO 更新 id(您的实体的主键)复制属性。

您可以存储密钥、复制属性和恢复。

     Long oldId=application.getId();
     BeanUtils.copyProperties(application, applicationDTO);
     application.setId(oldId);
     appId=application.getAPP_ID();

【讨论】:

  • 不确定是这个问题,错误消息是关于 Pricing#id
  • 不看代码真代码很难说。以某种方式更改了主键列。这就是原因。
  • 是的,某些“定价”实例的 ID 以某种方式更改了,我同意
  • 在事务注释中尝试了可序列化的隔离...仍然得到异常
猜你喜欢
  • 2011-05-09
  • 1970-01-01
  • 2012-08-14
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多