Uploaded image for project: 'MariaDB Connector/J'
  1. MariaDB Connector/J
  2. CONJ-344

HibernateOptimisticLockingFailureException with Hibernate, Mariadb and Spring transactions

    XMLWordPrintable

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Not a Bug
    • None
    • N/A
    • Other
    • None

    Description

      We are migrating application from oracle to Mariadb. Using container transactions and Spring transaction management. I am getting error for code where the one record is saved and updated in same transaction(Service bean method). Same code is working fine for Oracle database.

      I am the only one who is connected to the mariadb database. Help will be appreciated.

      Error:

      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

      JDK: 1.6, Tomcat: 7.0.65, Spring: 4.1, hibernate: 4.2.21

      mariadb version: 10.1.13-MariaDB

      driver: mariadb-java-client-1.1.9

      Dialects: org.hibernate.dialect.MySQLInnoDBDialect

      and i tried with org.hibernate.dialect.MySQLDialect also same error is coming.

      @Entity
      @Table(name = "DEAL")
      public class Deal implements Serializable {
       
          private static final long serialVersionUID = 1196605299069938794L;
       
          @Id
          @Column(name = "SK_DEAL_ID")
          @GeneratedValue(strategy = GenerationType.TABLE, generator = "Deal_SEQ")
          @TableGenerator(name = "Deal_SEQ", pkColumnValue = "DEAL_SEQUENCE", allocationSize = 1)
          @Access(AccessType.PROPERTY)
          private Long id;
       
          @Column(name = "INT_DEAL_ID", length = 50)
          private String internalDealId;
       
          @Column(name = "DEAL_DESC", length = 100)
          private String description;
       
          @ManyToOne(fetch = FetchType.LAZY)
          @JoinColumn(name = "LAST_UPDATED_ID")
          private SysUser lastUpdatedId;
       
          @Version
          @Type(type = "timestamp")
          @Column(name = "LAST_UPDATED")
          private Date lastUpdated;
       
          @Type(type = "timestamp")
          @Column(name = "CREATION_DATE")
          private Date creationDate;
       
          @Type(type = "timestamp")
          @Column(name = "CREATION_DATE_USER_TZ")
          private Date creationDateUserTz;
       
          @Type(type = "date")
          @Column(name = "END_DATE")
          private Date endDate;
       
       
          public Long getId() {
              return id;
          }
       
          public void setId(Long id) {
              this.id = id;
          }
       
          public String getInternalDealId() {
              return this.internalDealId;
          }
       
          public void setInternalDealId(String internalDealId) {
              this.internalDealId = internalDealId;
          }
       
       
          public String getDescription() {
              return this.description;
          }
       
          public void setDescription(String description) {
              this.description = description;
          }
       
          public SysUser getLastUpdatedId() {
              return this.lastUpdatedId;
          }
       
          public void setLastUpdatedId(SysUser lastUpdatedId) {
              this.lastUpdatedId = lastUpdatedId;
          }
       
          public Date getLastUpdated() {
              return this.lastUpdated;
          }
       
          public void setLastUpdated(Date lastUpdated) {
              this.lastUpdated = lastUpdated;
          }
       
          public Date getCreationDate() {
              return this.creationDate;
          }
       
          public void setCreationDate(Date creationDate) {
              this.creationDate = creationDate;
          }
       
          public Date getCreationDateUserTz() {
              return creationDateUserTz;
          }
       
          public void setCreationDateUserTz(Date creationDateUserTz) {
              this.creationDateUserTz = creationDateUserTz;
          }
       
          public Date getEndDate() {
              return endDate;
          }
       
          public void setEndDate(Date endDate) {
              this.endDate = endDate;
          }
       
       
          @Override
          public String toString() {
              return new StringBuilder("{")
              .append("id=").append(id)
              .append(",internalDealId=").append(internalDealId)
              .append(",description=").append(description)
              .append(",lastUpdatedId=").append(lastUpdatedId != null ? lastUpdatedId.getId() : null)
              .append(",lastUpdated=").append(lastUpdated)
              .append(",creationDate=").append(creationDate)
              .append(",creationDateUserTz=").append(creationDateUserTz)
              .append(",endDate=").append(endDate)
              .append("}")
              .toString();
          }
       
      }
      

      Service class method

      @Override
          @Target({ ElementType.METHOD, ElementType.TYPE })
          @Retention(RetentionPolicy.RUNTIME)
          @Transactional(readOnly = false, rollbackFor = Exception.class)
          public DealVO addNew(DealVO vo) {
              Deal deal = new Deal();
              vo.setEndDate(new Date());
              deal = convertDealVOToDeal(vo, deal);
              dealDao.save(deal);
              //Some other logic based on creation date
              //setting some other deal properties
              dealDao.save(deal);
              //original logger is removed as it contains sensitive deal info
              vo.setCreationDate(deal.getCreationDate());
              vo.setCreationDateUserTz(deal.getCreationDateUserTz());
              vo.setId(deal.getId());
              return vo;
          }
      

      Dao class methods:

      public Session getSession() {
              return getSessionFactory().getCurrentSession();
          }
       
          @Override
          @Target({ ElementType.METHOD, ElementType.TYPE })
          @Retention(RetentionPolicy.RUNTIME)
          @Transactional(readOnly = false, rollbackFor = Exception.class)
          public void save(T domain) {
              getSession().saveOrUpdate(domain);
          }
      
      

      Queries generated after control coming out of service method

      insert into DEAL (INT_DEAL_ID, DEAL_DESC, LAST_UPDATED_ID, CREATION_DATE, CREATION_DATE_USER_TZ, END_DATE, SK_DEAL_ID) values (?, ?, ?, ?, ?, ?, ?)
       
      update DEAL set INT_DEAL_ID=?, DEAL_DESC=?, LAST_UPDATED_ID=?, CREATION_DATE=?, CREATION_DATE_USER_TZ=?, END_DATE=? where SK_DEAL_ID=? and LAST_UPDATED=?
      

      Attachments

        Activity

          People

            diego dupin Diego Dupin
            kalari.82@gmail.com sunil k
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.