1
votes

Oracle Table 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. T_JOB is a Transaction table. 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). 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,

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]

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]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:181) at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:680)

Please help me to sort out this issue.

3
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). But while selecting job details, I need both service_Name.Tech Mahesh

3 Answers

0
votes

The error occurs because there are 2 transactions working on the same record. 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.

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.
0
votes

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);
0
votes

You have onedirectional relation. You have to add in your ServiceVO class:

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

This code creates bidirectional relation, and I think it fix your problem.