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