KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > id > TableGenerator


1 //$Id: TableGenerator.java,v 1.21 2005/07/04 02:40:29 oneovthafew Exp $
2
package org.hibernate.id;
3
4 import java.io.Serializable JavaDoc;
5 import java.sql.Connection JavaDoc;
6 import java.sql.PreparedStatement JavaDoc;
7 import java.sql.ResultSet JavaDoc;
8 import java.sql.SQLException JavaDoc;
9 import java.sql.Types JavaDoc;
10 import java.util.Properties JavaDoc;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.hibernate.HibernateException;
15 import org.hibernate.LockMode;
16 import org.hibernate.dialect.Dialect;
17 import org.hibernate.engine.SessionImplementor;
18 import org.hibernate.engine.TransactionHelper;
19 import org.hibernate.mapping.Table;
20 import org.hibernate.type.Type;
21 import org.hibernate.util.PropertiesHelper;
22
23 /**
24  * An <tt>IdentifierGenerator</tt> that uses a database
25  * table to store the last generated value. It is not
26  * intended that applications use this strategy directly.
27  * However, it may be used to build other (efficient)
28  * strategies. The returned type is <tt>Integer</tt>.<br>
29  * <br>
30  * The hi value MUST be fetched in a seperate transaction
31  * to the <tt>Session</tt> transaction so the generator must
32  * be able to obtain a new connection and commit it. Hence
33  * this implementation may not be used when Hibernate is
34  * fetching connections when the user is supplying
35  * connections.<br>
36  * <br>
37  * The returned value is of type <tt>integer</tt>.<br>
38  * <br>
39  * Mapping parameters supported: table, column
40  *
41  * @see TableHiLoGenerator
42  * @author Gavin King
43  */

44 public class TableGenerator extends TransactionHelper
45     implements PersistentIdentifierGenerator, Configurable {
46     /* COLUMN and TABLE should be renamed but it would break the public API */
47     /** The column parameter */
48     public static final String JavaDoc COLUMN = "column";
49     
50     /** Default column name */
51     public static final String JavaDoc DEFAULT_COLUMN_NAME = "next_hi";
52     
53     /** The table parameter */
54     public static final String JavaDoc TABLE = "table";
55     
56     /** Default table name */
57     public static final String JavaDoc DEFAULT_TABLE_NAME = "hibernate_unique_key";
58
59     private static final Log log = LogFactory.getLog(TableGenerator.class);
60
61     private String JavaDoc tableName;
62     private String JavaDoc columnName;
63     private String JavaDoc query;
64     private String JavaDoc update;
65
66     public void configure(Type type, Properties JavaDoc params, Dialect dialect) {
67
68         this.tableName = PropertiesHelper.getString(TABLE, params, DEFAULT_TABLE_NAME);
69         this.columnName = PropertiesHelper.getString(COLUMN, params, DEFAULT_COLUMN_NAME);
70         String JavaDoc schemaName = params.getProperty(SCHEMA);
71         String JavaDoc catalogName = params.getProperty(CATALOG);
72
73         if (tableName.indexOf(dialect.getSchemaSeparator() )<0) {
74             tableName = Table.qualify( catalogName, schemaName, tableName, dialect.getSchemaSeparator() );
75         }
76
77         query = "select " +
78             columnName +
79             " from " +
80             dialect.appendLockHint(LockMode.UPGRADE, tableName) +
81             dialect.getForUpdateString();
82
83         update = "update " +
84             tableName +
85             " set " +
86             columnName +
87             " = ? where " +
88             columnName +
89             " = ?";
90     }
91
92     public synchronized Serializable JavaDoc generate(SessionImplementor session, Object JavaDoc object)
93         throws HibernateException {
94         int result = ( (Integer JavaDoc) doWorkInNewTransaction(session) ).intValue();
95         return new Integer JavaDoc(result);
96     }
97
98
99     public String JavaDoc[] sqlCreateStrings(Dialect dialect) throws HibernateException {
100         return new String JavaDoc[] {
101             "create table " + tableName + " ( " + columnName + " " + dialect.getTypeName(Types.INTEGER) + " )",
102             "insert into " + tableName + " values ( 0 )"
103         };
104     }
105
106     public String JavaDoc[] sqlDropStrings(Dialect dialect) {
107         //return "drop table " + tableName + dialect.getCascadeConstraintsString();
108
StringBuffer JavaDoc sqlDropString = new StringBuffer JavaDoc()
109             .append("drop table ");
110         if ( dialect.supportsIfExistsBeforeTableName() ) sqlDropString.append("if exists ");
111         sqlDropString.append(tableName)
112             .append( dialect.getCascadeConstraintsString() );
113         if ( dialect.supportsIfExistsAfterTableName() ) sqlDropString.append(" if exists");
114         return new String JavaDoc[] { sqlDropString.toString() };
115     }
116
117     public Object JavaDoc generatorKey() {
118         return tableName;
119     }
120
121     public Serializable JavaDoc doWorkInCurrentTransaction(Connection JavaDoc conn, String JavaDoc sql) throws SQLException JavaDoc {
122         int result;
123         int rows;
124         do {
125             // The loop ensures atomicity of the
126
// select + update even for no transaction
127
// or read committed isolation level
128

129             sql = query;
130             SQL.debug(query);
131             PreparedStatement JavaDoc qps = conn.prepareStatement(query);
132             try {
133                 ResultSet JavaDoc rs = qps.executeQuery();
134                 if ( !rs.next() ) {
135                     String JavaDoc err = "could not read a hi value - you need to populate the table: " + tableName;
136                     log.error(err);
137                     throw new IdentifierGenerationException(err);
138                 }
139                 result = rs.getInt(1);
140                 rs.close();
141             }
142             catch (SQLException JavaDoc sqle) {
143                 log.error("could not read a hi value", sqle);
144                 throw sqle;
145             }
146             finally {
147                 qps.close();
148             }
149
150             sql = update;
151             SQL.debug(update);
152             PreparedStatement JavaDoc ups = conn.prepareStatement(update);
153             try {
154                 ups.setInt( 1, result + 1 );
155                 ups.setInt( 2, result );
156                 rows = ups.executeUpdate();
157             }
158             catch (SQLException JavaDoc sqle) {
159                 log.error("could not update hi value in: " + tableName, sqle);
160                 throw sqle;
161             }
162             finally {
163                 ups.close();
164             }
165         }
166         while (rows==0);
167         return new Integer JavaDoc(result);
168     }
169 }
170
Popular Tags