SuperX-Kernmodul
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

602 lines
18 KiB

package de.memtext.db;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import de.memtext.baseobjects.NamedIdObject;
import de.memtext.baseobjects.NamedIdObjectWithParent;
import de.memtext.baseobjects.coll.NamedIdObjectList;
import de.memtext.baseobjects.coll.NamedIdObjectWithParentList;
import de.memtext.tree.KeyParentEqualException;
import de.memtext.util.StringUtils;
/**
* This class faciliates access to databases. It offers easy standardized
* access. To start with one has to call the create method with an existing
* Connection to the database and a name for this connection. In other parts of
* your programme database access is possible using
* DBAccess.get("connectionname").function
*
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt,
* daher nicht einfach entfernen.
*
* @author: MB
*/
public class DBAccess {
private String name;
private Connection con = null;
private Statement stmt = null;
private boolean isInJar = false;
private int updateCount;
private static IllegalStateException illegalStateEx = new IllegalStateException(
"DBAccess not inited - connection is null");
private static Map<String, DBAccess> entries = new HashMap<String, DBAccess>();
public static DBAccess get(String name) {
DBAccess one = entries.get(name);
if (one != null) {
Connection con = one.getConnection();
try {
if (con.isClosed()) {
throw new RuntimeException("DBAccess: Connection already closed!");
}
} catch (SQLException e) {
throw new RuntimeException("DBAccess: Cannot check for closed connection.", e);
}
}
return one;
}
public Connection getConn() {
return con;
}
public static boolean hasConnection(String name) {
return entries.containsKey(name);
}
/**
*
* when adding an hsqldb connection also notices from the url if the db is
* inside a jar, can be questioned by isInJar()
*
* @param name
* @param con
* @throws SQLException
*
*/
public static void addConnection(String name, Connection con) throws SQLException {
DBAccess dba = DBAccess.get(name);
if (dba != null && !dba.getConnection().isClosed()) {
// System.out.println("There is already an entry with the name " + name);
} else {
entries.put(name, new DBAccess(name, con));
}
}
public static void removeConnection(String name) throws SQLException {
DBAccess dba = DBAccess.get(name);
if (dba != null && !dba.getConnection().isClosed()) {
dba.closeConnection();
entries.remove(name);
}
}
public void closeConnection() throws SQLException {
if (stmt != null)
stmt.close();
con.close();
con = null;
entries.remove(this);
}
static public void closeConnection(String name) throws SQLException {
DBAccess.get(name).closeConnection();
}
private DBAccess(String name, Connection con) throws SQLException {
this.name = name;
this.con = con;
if (con.getMetaData().getDriverName().equals("HSQL Database Engine Driver")
&& con.getMetaData().getURL().indexOf("res:") > 0)
isInJar = true;
stmt = con.createStatement();
}
/**
* Returns the java.sql.Connection with the given name. Normally get(name)
* returns a DBAccess object this method is only used when the very Connection
* is needed.
*
* @param name
* @return
*/
public Connection getConnection() {
return con;
}
/**
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @return
*/
public boolean isInJar() {
return isInJar;
}
public String getName() {
return name;
}
/**
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @return
* @throws SQLException
*/
public String getTableNames() throws SQLException {
StringBuffer result = new StringBuffer("Tabellen in der Datenbank:");
DatabaseMetaData meta = con.getMetaData();
ResultSet rs = null;
rs = meta.getTables(null, null, null, null);
while (rs.next()) {
result.append(rs.getObject(3) + " ");
}
rs.close();
return result.toString();
}
public boolean hasTable(String tablename) throws SQLException {
boolean result = false;
ResultSet rs = con.getMetaData().getTables(null, null, null, null);
while (rs.next()) {
if (tablename.equalsIgnoreCase(rs.getObject(3).toString())) {
result = true;
break;
}
}
rs.close();
return result;
}
public static boolean hasTable(Connection c, String tablename) throws SQLException {
boolean result = false;
ResultSet rs = c.getMetaData().getTables(null, null, null, null);
while (rs.next()) {
if (tablename.equalsIgnoreCase(rs.getObject(3).toString())) {
result = true;
break;
}
}
rs.close();
return result;
}
/**
* select key from blueprint; _> "1,2,3,4,5,6,7"
*
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt,
* daher nicht einfach entfernen.
*
* @param sql separator is comma null is ignored
* @throws SQLException
*/
public StringBuffer getSeperatedString(String sql) throws SQLException {
return getSeperatedString(sql, ",");
}
/**
* select key from blueprint; _> "'1','2','3','4','5','6','7'" WICHTIG: Einige
* Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht
* einfach entfernen.
*
* @param sql
* @param separator null is ignored
* @throws SQLException
*/
public StringBuffer getSeperatedString(String sql, String separator) throws SQLException {
StringBuffer erg = new StringBuffer();
ResultSet result = stmt.executeQuery(sql);
Object value;
while (result.next()) {
value = result.getObject(1);
if (value == null)
erg.append("null" + separator);
else
erg.append("'" + value + "'" + separator);
}
result.close();
if (erg.length() > 0)
StringUtils.deleteLastChar(erg);
return erg;
}
/**
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt,
* daher nicht einfach entfernen.
*
* @param pstSql
* @param args
* @return
* @throws SQLException
*/
public String getString(String pstSql, Object... args) throws SQLException {
String erg = null;
PreparedStatement pst = null;
ResultSet rs = null;
pst = this.con.prepareStatement(pstSql);
int paramPos = 1;
for (Object arg : args) {
pst.setObject(paramPos, arg);
paramPos++;
}
rs = pst.executeQuery();
while (rs.next()) {
erg = rs.getString(1);
break;
}
rs.close();
return erg;
}
public int execute(String sql) throws SQLException {
if (con == null)
throw illegalStateEx;
updateCount = stmt.executeUpdate(sql);
return updateCount;
}
public ResultSet executeQuery(String sql) throws SQLException {
if (con == null)
throw illegalStateEx;
if (stmt != null)
stmt.close();
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
return rs;
}
/**
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @param prefix
* @return
* @throws SQLException
*/
public Object[] getTablesStartingWith(String prefix) throws SQLException {
if (con == null)
throw illegalStateEx;
ArrayList list = new ArrayList();
ResultSet rs = con.getMetaData().getTables(null, null, prefix + "%", null);
while (rs.next()) {
list.add(rs.getString(3));
}
rs.close();
Object[] result = list.toArray();
Arrays.sort(result);
return result;
}
/**
* Es wird einfach das erste Objekt der ersten Spalte genommen
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @param sql
* @return
* @throws SQLException
*/
public Double getDoubleValue(String sql) throws SQLException {
Double val = null;
ResultSet rs = executeQuery(sql);
rs.next();
Object o = rs.getObject(1);
rs.close();
if (o instanceof Double)
val = (Double) o;
else if (o instanceof java.math.BigDecimal) {
BigDecimal merk = (BigDecimal) o;
val = Double.valueOf(merk.doubleValue());
} else if (o != null)
val = Double.valueOf(o.toString());
return val;
}
/**
* Method hasColumn. can be problem for other databases.
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @param aTablename
* @param string
* @return boolean
* @throws SQLException
*/
public boolean hasColumn(String aTablename, String colname) throws SQLException {
if (con == null)
throw illegalStateEx;
boolean result = false;
if (!hasTable(aTablename))
throw new IllegalArgumentException("Database doesn't contain table " + aTablename);
// Hsql had problems with metadata stuff
ResultSet rs = con.getMetaData().getColumns(null, null, aTablename.toUpperCase(), colname.toUpperCase());
// ResultSetMetaData rsmd = rs.getMetaData();
// int numberOfColumns = rsmd.getColumnCount();
while (rs.next()) {
// wenn etwas gefunden wurde, gibt's die Spalte
result = true;
}
rs.close();
return result;
}
public int getInt(String query, Object... args) throws SQLException {
Integer result = getInteger(query, args);
if (result == null)
throw new RuntimeException("nothing or null found");
return result.intValue();
}
/*
* If more than one value is found, only considers the first
*/
public Integer getInteger(String pstSQL, Object... args) throws SQLException {
Integer erg = null;
PreparedStatement pst = null;
ResultSet rs = null;
pst = this.con.prepareStatement(pstSQL);
int paramPos = 1;
for (Object arg : args) {
pst.setObject(paramPos, arg);
paramPos++;
}
rs = pst.executeQuery();
Object o = null;
boolean isFirst = true;
while (rs.next()) {
if (isFirst) {
o = rs.getObject(1);
isFirst = false;
}
}
if (o != null) {
if (o instanceof Integer)
erg = (Integer) o;
else if (o instanceof Long)
erg = Integer.valueOf(((Long) o).intValue());
else if (o instanceof Short)
erg = Integer.valueOf(((Short) o).intValue());
else {
throw new IllegalArgumentException(
"Unbekannter Datentyp in DBAccess getInteger:" + o.getClass() + " - " + pstSQL);
}
}
rs.close();
return erg;
}
/**
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @return
* @throws SQLException
*/
public List getTableList() throws SQLException {
if (con == null)
throw illegalStateEx;
List result = new LinkedList();
ResultSet rs = con.getMetaData().getTables(null, null, null, null);
while (rs.next()) {
result.add(rs.getObject(3).toString());
}
rs.close();
return result;
}
/**
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt,
* daher nicht einfach entfernen.
*
* @param sql
* @return List in LIst!!
* @throws SQLException
*/
public List getResultList(String sql) throws SQLException {
List result = new LinkedList();
ResultSet rs = executeQuery(sql);
result = DbUtils.toResultList(rs);
rs.close();
return result;
}
/**
* Hsql needs uppercase!
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @throws SQLException
*/
public int getColumnType(String tablename, String colname) throws SQLException {
int result = -9999;
if (!hasTable(tablename))
throw new RuntimeException("Database doesn't contain table " + tablename);
if (!hasColumn(tablename, colname))
throw new RuntimeException("Table " + tablename + " doesn't have column:" + colname);
ResultSet rs = con.getMetaData().getColumns(null, null, tablename.toUpperCase(), colname.toUpperCase());
while (rs.next()) {
result = rs.getInt(5);
}
rs.close();
return result;
}
/*
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
*/
public int getColumnCount(String tablename) throws SQLException {
int result = 0;
if (!hasTable(tablename))
throw new RuntimeException("Database doesn't contain table " + tablename);
ResultSet rs = con.getMetaData().getColumns(null, null, tablename.toUpperCase(), null);
while (rs.next()) {
result++;
}
rs.close();
return result;
}
/**
* Hsql needs uppercase!
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @throws SQLException
*/
public List getColumnNames(String tablename) throws SQLException {
List result = new LinkedList();
if (!hasTable(tablename))
throw new RuntimeException("Database doesn't contain table " + tablename);
ResultSet rs = con.getMetaData().getColumns(null, null, tablename.toUpperCase(), null);
while (rs.next()) {
result.add(rs.getObject(4).toString());
}
rs.close();
return result;
}
/**
* Method executeAndCheckUpdate1Row.
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
* @param string
* @throws SQLException
*/
public void executeAndCheckUpdate1Row(String sql) throws SQLException {
int updateRowCount = execute(sql);
if (updateRowCount != 1)
throw new IllegalStateException("Es wurde nicht 1 Zeile geupdated, sondern " + updateRowCount);
}
/**
* Sets a property in the properties table of a db WICHTIG: Einige Methoden
* werden nicht für SuperX aber für Joolap benötigt, daher nicht einfach
* entfernen.
*
* @param key
* @param value
* @throws SQLException
*/
public void setProperty(String key, String value) throws SQLException {
if (key == null || value == null)
throw new IllegalArgumentException("no nulls allowed in properties table");
execute("delete from properties where name='key';insert into properties (name,value) values('" + key + "','"
+ value + "');");
}
/**
* Gets a property from the properties table WICHTIG: Einige Methoden werden
* nicht für SuperX aber für Joolap benötigt, daher nicht einfach entfernen.
*
* @param key
* @return String - null if nothing found
* @throws SQLException
*/
public String getProperty(String key) throws SQLException {
return getString("select value from properties where name='" + key + "'");
}
/**
* creates a java.util.List with NamedIDObjects from a table in the database
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt,
* daher nicht einfach entfernen.
*
* @param tablename - name of the source table
* @param idColName - name of the ID column in the table (e.g. tid)
* @param nameColName - name of the name column in the table (e.g. name or text)
* @param restriction - optionally a restriction like "where id>2" may be null
* @return NamedIdObjectList
*/
public NamedIdObjectList getNamedIdObjectList(String tablename, String idColName, String nameColName,
String restriction, String orderby, Class targetClass)
throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException, SQLException {
NamedIdObjectList result = new NamedIdObjectList();
if (restriction == null)
restriction = "";
Object id;
String name;
List rawList = getResultList(
"select " + idColName + "," + nameColName + " from " + tablename + " " + restriction + " " + orderby);
Class[] constparams = { Object.class, String.class };
Object[] data = new Object[2];
Constructor constr = targetClass.getConstructor(constparams);
for (Iterator it = rawList.iterator(); it.hasNext();) {
List row = (List) it.next();
id = row.get(0);
name = "";
if (row.get(1) != null)
name = row.get(1).toString();
data[0] = id;
data[1] = name;
Object o = constr.newInstance(data);
result.add(o);
}
return result;
}
/**
* WICHTIG: Einige Methoden werden nicht für SuperX aber für Joolap benötigt,
* daher nicht einfach entfernen.
*
* @param tablename
* @param idColName
* @param nameColName
* @param restriction
* @param orderby
*/
public NamedIdObjectList getNamedIdObjectList(String tablename, String idColName, String nameColName,
String restriction, String orderby) throws IllegalArgumentException, SQLException, SecurityException,
NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
NamedIdObjectList result = null;
result = getNamedIdObjectList(tablename, idColName, nameColName, restriction, orderby, NamedIdObject.class);
return result;
}
public NamedIdObjectWithParentList getNamedIdObjectWithParentList(String tablename, String idColName,
String nameColName, String restriction) throws KeyParentEqualException, SQLException {
NamedIdObjectWithParentList result = new NamedIdObjectWithParentList();
if (restriction == null)
restriction = "";
Object id;
String name;
Object parentKey;
NamedIdObjectWithParent one;
List rawList = getResultList(
"select " + idColName + "," + nameColName + ",parent from " + tablename + " " + restriction);
for (Iterator it = rawList.iterator(); it.hasNext();) {
List row = (List) it.next();
id = row.get(0);
name = "";
if (row.get(1) != null)
name = row.get(1).toString();
parentKey = row.get(2);
one = new NamedIdObjectWithParent(id, name, parentKey);
result.add(one);
}
return result;
}
public void execute(StringBuffer sql) throws SQLException {
execute(sql.toString());
}
}