简体   繁体   English

休眠一对一映射注释插入异常(在插入跨国表时,主表数据不应更改)

[英]Hibernate one to one mapping annotation insert exception (While inserting into transnational table, master table data should not change)

Oracle Table DDL: Oracle表DDL:

CREATE TABLE M_SERVICE
(
   SERVICE_ID    NUMBER (10) PRIMARY KEY,
   SERVICE_NM    VARCHAR2 (255),
   ACTIVE_SW     CHAR (1),
   LST_UPDT_DT   DATE,
   LST_UPDT_BY   VARCHAR2 (32)
)

CREATE TABLE T_JOB
(
   JOB_ID          NUMBER PRIMARY KEY,
   JOB_NM          VARCHAR2 (32),
   JOB_DESC        VARCHAR2 (2000),
   SERVICE_ID      NUMBER,
   DUE_DT          DATE,
   LST_UPDT_DT     DATE,
   LST_UPDT_BY     VARCHAR2 (32),
   CONSTRAINT T_JOB_FK1 FOREIGN KEY
      (SERVICE_ID)
       REFERENCES M_SERVICE (SERVICE_ID)
)

M_SERVICE is a master table. M_SERVICE是一个主表。 T_JOB is a Transaction table. T_JOB是一个事务表。 My requirement is, when I tried to insert in the T_job table should not insert/update in the M_service table (All the service_Id's are available in the M_SERVICE). 我的要求是,当我尝试在T_job表中插入时,不应在M_service表中插入/更新(所有service_Id在M_SERVICE中都可用)。 But while selecting, I need both table data. 但是在选择时,我需要两个表数据。

Entities: 实体:

@Entity
@Table(name = "M_SERVICE")
public class ServiceVO implements Serializable {
    private static final long serialVersionUID = -2684205897352720653L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SERVICE_ID")
    @SequenceGenerator(name = "SEQ_SERVICE_ID", sequenceName = "SEQ_SERVICE_ID")
    @Column(name = "SERVICE_ID")
    private Integer serviceId;

    @Column(name = "SERVICE_NM")
    private String serviceName;

    @Column(name = "ACTIVE_SW")
    private char activeSwitch;  

    @Column(name = "LST_UPDT_DT")
    @Temporal(TemporalType.DATE)
    private Date lastUpdatedDt;

    @Column(name = "LST_UPDT_BY")
    private String lastUpdatedBy;
 //Getter & Setters.
}

@Entity
@Table(name = "T_JOB")
public class JobVO implements Serializable {
    private static final long serialVersionUID = 7167763557817486917L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_JOB_ID")
    @SequenceGenerator(name = "SEQ_JOB_ID", sequenceName = "SEQ_JOB_ID")
    @Column(name = "JOB_ID")
    private Integer jobId;

    @Column(name = "JOB_NM", nullable = false)
    private String jobName;

    @Column(name = "JOB_DESC")
    private String jobDesc;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "SERVICE_ID", referencedColumnName = "SERVICE_ID", insertable = false, updatable = false)
    private ServiceVO service;

    @Column(name = "DUE_DT", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date dueDate;

    @Column(name = "LST_UPDT_DT", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date lastUpdatedDt;

    @Column(name = "LST_UPDT_BY", nullable = false)
    private String lastUpdatedBy;
//Getter & Setters.
}

If I call to get a particular job details based on job Id means, I can able to get as I expected like below, 如果我打电话要求根据工作ID表示特定的工作详细信息,那么我可以像下面期望的那样获得信息,

this.sessionFactory.getCurrentSession().get(JobVO.class, id);

JobVO [jobId=1, jobName=job name, jobDesc=desc, service=ServiceVO [serviceId=2, serviceName=Tax Audit, activeSwitch=Y, lastUpdatedDt=2013-08-31, lastUpdatedBy=MAHESH], dueDate=2013-09-01, lastUpdatedDt=2013-09-01, lastUpdatedBy=mahesh] JobVO [jobId = 1,jobName = job name,jobDesc = desc,service = ServiceVO [serviceId = 2,serviceName = Tax Audit,activeSwitch = Y,lastUpdatedDt = 2013-08-31,lastUpdatedBy = MAHESH],dueDate = 2013-09 -01,lastUpdatedDt = 2013-09-01,lastUpdatedBy = mahesh]

But if I tried to insert a job means, 但是,如果我尝试插入工作方式,

            JobVO jobVO = new JobVO();
        jobVO.setAuditorId(1);                  
        jobVO.setDueDate(new Date());
        jobVO.setJobDesc("VAT1");
        jobVO.setJobName("Account");
        jobVO.setLastUpdatedBy("Mahesh");
        jobVO.setLastUpdatedDt(new Date());
        ServiceVO service=new ServiceVO();
        service.setServiceId(getClientId());
        jobVO.setService(service);
            this.sessionFactory.getCurrentSession().persist(jobVO);

Getting Error like as below, org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; 出现如下所示的错误,org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException:批处理更新从更新[0]返回了意外的行数; actual row count: 0; 实际行数:0; expected: 1; 预期:1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; 嵌套的异常是org.hibernate.StaleStateException:批处理更新从更新[0]返回了意外的行数; actual row count: 0; 实际行数:0; expected: 1 at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:181) at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:680) 预期:org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:680)处org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:181)为1

Please help me to sort out this issue. 请帮助我解决此问题。

The error occurs because there are 2 transactions working on the same record. 发生错误是因为有2个事务在同一记录上工作。 If a record is read by 2 transactions, and if the record is saved by one transaction first, an optimistic locking exception is thrown in the second transaction, because the system assumes that nobody else is going to modify the record. 如果一个记录被2个事务读取,并且如果该记录首先被一个事务保存,则在第二个事务中将抛出乐观锁定异常,因为系统假定其他人都不会修改该记录。

Are you using multithreading in batch mode? 您是否在批处理模式下使用多线程?

There are different solutions: 有不同的解决方案:

  1. Make sure that records that are going to be updated, are touched by only a single transaction at any given moment 确保在任何给定时刻仅一次事务处理将要更新的记录
  2. Retry the transaction: Make sure that no non-transactional state is kept between the retries. 重试事务:确保重试之间不保留任何非事务状态。

You have onedirectional relation. 您具有单向关系。 You have to add in your ServiceVO class: 您必须添加ServiceVO类:

@OneToOne(fetch = FetchType.LAZY, mappedBy = "service")
private JobVO job;

This code creates bidirectional relation, and I think it fix your problem. 这段代码创建了双向关系,我认为它可以解决您的问题。

Please try this. 请尝试这个。

    ServiceVO service=new ServiceVO();
    service.setServiceId(getClientId());
    this.sessionFactory.getCurrentSession().saveOrUpdate(service);

    JobVO jobVO = new JobVO();
    jobVO.setAuditorId(1);      
    jobVO.setClientId(getClientId());       
    jobVO.setDueDate(new Date());
    jobVO.setJobDesc("VAT1");
    jobVO.setJobName("Account");
    jobVO.setLastUpdatedBy("Mahesh");
    jobVO.setLastUpdatedDt(new Date());
    jobVO.setService(service);
    this.sessionFactory.getCurrentSession().saveOrUpdate(jobVO);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM