Id of entity is different after hibernate save from oracle database with sequence autogeneration id

Tags: , ,



Entity with id autogenerated from oracle trigger sequence.

@Entity
@Table(name = "REPORT", schema = "WEBPORTAL")
public class Report {
    private Integer id;
....


    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="report_sequence")
    @SequenceGenerator(name="report_sequence", sequenceName = "report_id_seq")
    @Column(name="REPORT_ID", unique = true, nullable = false)
    public Integer getId() {
        return id;
    }
....
}

Service

@Service("reportService")
public class ReportServiceImpl implements ReportService {
....

    @Transactional(readOnly=false)
    public void saveOrUpdate(Report report) {
        reportDAO.saveOrUpdate(report);
    }
}

DAO

@Repository
public class ReportDAOImpl implements ReportDAO {
....

    @Override
    public Report save(Report report) {
        try {
           Session session = sessionFactory.getCurrentSession();
           session.save(report);
        } catch (Exception e) {
           logger.error("error", e);
        }
        return report;
    }
}

And When I call service’s saveOrUpdate and then try to reach id of entity I get different value than persisted in database. Values on database with autogeneration all is ok. Any suggestions?

reportService.saveOrUpdate(report);
System.out.println(report.getId());

prints: 4150 but saved id in database is: 84

NOTE: My purpose to get Id comes from that I wanted to save childs with cascade. But foreign key on child was different in database(the values of id that I get with getId()).

And Id generated in database is incremented by 2. EX: 80, 82, 84.

UPDATE:

Oracle trigger for sequence generation

CREATE OR REPLACE TRIGGER REPORT_ID_TRIG    
BEFORE INSERT ON WEBPORTAL.REPORT  
FOR EACH ROW   
BEGIN   
    SELECT report_id_seq.NEXTVAL  
    INTO :new.report_id  
    FROM dual;  
END;  

Answer

ANSWER: Trigger should check if id is null

CREATE OR REPLACE TRIGGER REPORT_ID_TRIG
BEFORE INSERT ON WEBPORTAL.REPORT
FOR EACH ROW
WHEN (new.report_id is null)
BEGIN 
    SELECT report_id_seq.NEXTVAL
    INTO :new.report_id
    FROM dual;
END;

DESCRIPTION:
@GeneratedValue is not just a sequence generator. It’s bit of HiLo algorithm.When it first requests id from database it multiplies it with 50(it can differ) and next 50 new entities will be given ids consequently, and than next request to database. This is to decrease request to database.
The numbers that I get from java was right numbers that should be saved on report.

Without id null value check Hibernate firstly requested for id from database and sequence.nextval called. When hibernate was persisting it(completing transaction) the database called sequence.next second time and set that value to database. So on ReportDetails there was true id value of report and on the Report id it was id set from database.



Source: stackoverflow