Added auto-migration for adding new columns.
This commit is contained in:
@@ -22,6 +22,7 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -29,6 +30,7 @@ import java.sql.Statement;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
@@ -37,6 +39,7 @@ import javax.persistence.TableGenerator;
|
|||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
|
|
||||||
import com.samskivert.jdbc.JDBCUtil;
|
import com.samskivert.jdbc.JDBCUtil;
|
||||||
|
import com.samskivert.util.ListUtil;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import static com.samskivert.jdbc.depot.Log.log;
|
import static com.samskivert.jdbc.depot.Log.log;
|
||||||
@@ -227,11 +230,11 @@ public class DepotMarshaller<T>
|
|||||||
// now create the table for our persistent class if it does not exist
|
// now create the table for our persistent class if it does not exist
|
||||||
if (!JDBCUtil.tableExists(conn, getTableName())) {
|
if (!JDBCUtil.tableExists(conn, getTableName())) {
|
||||||
log.fine("Creating table " + getTableName() +
|
log.fine("Creating table " + getTableName() +
|
||||||
" (" + StringUtil.join(_columnDefinitions, ", ") + ") " +
|
" (" + StringUtil.join(_columnDefinitions, ", ") + ") " +
|
||||||
_postamble);
|
_postamble);
|
||||||
JDBCUtil.createTableIfMissing(
|
JDBCUtil.createTableIfMissing(
|
||||||
conn, getTableName(), _columnDefinitions, _postamble);
|
conn, getTableName(), _columnDefinitions, _postamble);
|
||||||
// TODO: insert current version into version table
|
updateVersion(conn, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have a key generator, initialize that too
|
// if we have a key generator, initialize that too
|
||||||
@@ -244,14 +247,54 @@ public class DepotMarshaller<T>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, then make sure the versions match and do some migration
|
// make sure the versions match
|
||||||
// if they don't
|
int currentVersion = readVersion(conn);
|
||||||
Statement stmt = conn.createStatement();
|
if (currentVersion == _schemaVersion) {
|
||||||
try {
|
return;
|
||||||
// TODO: magical migration; execute registered migration actions
|
|
||||||
} finally {
|
|
||||||
stmt.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info("Migrating " + getTableName() + " from " + currentVersion +
|
||||||
|
" to " + _schemaVersion + "...");
|
||||||
|
|
||||||
|
// otherwise try to migrate the schema; doing column additions
|
||||||
|
// magically and running any registered hand-migrations
|
||||||
|
DatabaseMetaData meta = conn.getMetaData();
|
||||||
|
ResultSet rs = meta.getColumns(null, null, getTableName(), "%");
|
||||||
|
HashSet<String> columns = new HashSet<String>();
|
||||||
|
while (rs.next()) {
|
||||||
|
columns.add(rs.getString("COLUMN_NAME"));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FieldMarshaller fmarsh : _fields.values()) {
|
||||||
|
if (columns.contains(fmarsh.getColumnName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise add the column
|
||||||
|
String coldef = fmarsh.getColumnDefinition();
|
||||||
|
String query = "alter table " + getTableName() +
|
||||||
|
" add column " + coldef;
|
||||||
|
|
||||||
|
// try to add it to the appropriate spot
|
||||||
|
int fidx = ListUtil.indexOf(_allFields, fmarsh.getColumnName());
|
||||||
|
if (fidx == 0) {
|
||||||
|
query += " first";
|
||||||
|
} else {
|
||||||
|
query += " after " + _allFields[fidx-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Adding column to " + getTableName() + ": " + coldef);
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
try {
|
||||||
|
stmt.executeUpdate(query);
|
||||||
|
} finally {
|
||||||
|
stmt.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: run any registered hand migrations
|
||||||
|
|
||||||
|
updateVersion(conn, _schemaVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -494,6 +537,36 @@ public class DepotMarshaller<T>
|
|||||||
return pstmt;
|
return pstmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void updateVersion (Connection conn, int version)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
String query = (version == 1) ?
|
||||||
|
"insert into " + SCHEMA_VERSION_TABLE +
|
||||||
|
" values('" + getTableName() + "', " + version + ")" :
|
||||||
|
"update " + SCHEMA_VERSION_TABLE + " set version = " + version +
|
||||||
|
" where persistentClass = '" + getTableName() + "'";
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
try {
|
||||||
|
stmt.executeUpdate(query);
|
||||||
|
} finally {
|
||||||
|
stmt.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int readVersion (Connection conn)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
String query = "select version from " + SCHEMA_VERSION_TABLE +
|
||||||
|
" where persistentClass = '" + getTableName() + "'";
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
try {
|
||||||
|
ResultSet rs = stmt.executeQuery(query);
|
||||||
|
return (rs.next()) ? rs.getInt(1) : 1;
|
||||||
|
} finally {
|
||||||
|
stmt.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** The persistent object class that we manage. */
|
/** The persistent object class that we manage. */
|
||||||
protected Class<T> _pclass;
|
protected Class<T> _pclass;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user