001package io.ebean.config.dbplatform; 002 003import io.ebean.Transaction; 004import io.ebean.util.JdbcClose; 005 006import javax.persistence.PersistenceException; 007import javax.sql.DataSource; 008import java.sql.Connection; 009import java.sql.PreparedStatement; 010import java.sql.ResultSet; 011import java.sql.SQLException; 012 013/** 014 * A very simple Database sequence based IdGenerator. 015 * <p> 016 * One which batch requests sequence Id's would be better for performance. 017 * </p> 018 */ 019public class SimpleSequenceIdGenerator implements PlatformIdGenerator { 020 021 private final String sql; 022 private final DataSource dataSource; 023 private final String seqName; 024 025 /** 026 * Construct given a dataSource and sql to return the next sequence value. 027 */ 028 public SimpleSequenceIdGenerator(DataSource dataSource, String sql, String seqName) { 029 this.dataSource = dataSource; 030 this.sql = sql; 031 this.seqName = seqName; 032 } 033 034 @Override 035 public String getName() { 036 return seqName; 037 } 038 039 @Override 040 public boolean isDbSequence() { 041 return true; 042 } 043 044 @Override 045 public void preAllocateIds(int batchSize) { 046 // just ignore this 047 } 048 049 @Override 050 public Object nextId(Transaction t) { 051 052 boolean useTxnConnection = t != null; 053 054 Connection c = null; 055 PreparedStatement pstmt = null; 056 ResultSet rset = null; 057 try { 058 c = useTxnConnection ? t.connection() : dataSource.getConnection(); 059 pstmt = c.prepareStatement(sql); 060 rset = pstmt.executeQuery(); 061 if (rset.next()) { 062 return rset.getInt(1); 063 } else { 064 String m = "Always expecting 1 row from " + sql; 065 throw new PersistenceException(m); 066 } 067 } catch (SQLException e) { 068 throw new PersistenceException("Error getting sequence nextval", e); 069 070 } finally { 071 if (useTxnConnection) { 072 closeResources(rset, pstmt, null); 073 } else { 074 closeResources(rset, pstmt, c); 075 } 076 } 077 } 078 079 private void closeResources(ResultSet rset, PreparedStatement pstmt, Connection c) { 080 JdbcClose.close(rset); 081 JdbcClose.close(pstmt); 082 JdbcClose.close(c); 083 } 084 085}