Java Datenbankklasse gesucht

Marius Heil

Erfahrenes Mitglied
Hi,

soweit ich das verstehe ist Java ja eine schwer Objektorientierte Sprache derer Vorteil darin besteht Klassen weiterverwenden zu können.
Ich habe jedoch hier im Forum und auch so im Internet keine tollen Klassensammlungen entdeckt die man verwenden könnte, außer einigen "offiziellen".

Ich bin auf der Suche nach einer Klasse mit der ich relativ einfach eine Datenbank abfragen kann. Da sollte man in einer Zeile ein Prepared statement anlegen können und mit einer weiteren das ausführen und als Rückgabe ein Mehrdimensionales assoziatives Array (Oder Hasmap / Hastable, was auch immer) erhalten.
Gibt es sowas im Internet zu finden oder muss ich mir das erst selbst schreiben?

Viele Grüße
 
Danke dir, das geht in die Richtige Richtung.
So 100%ig gefällt es mir noch nicht (Kann auch daran liegen, dass ich die Beispiele noch nciht ganz verstanden habe), man muss immer noch einige Zeilen Code schreiben damit das tut was es tun soll.
---------------------
Hier mal meine Vorstellung wie das ganze richtig schön und einfach funktionieren könnte:
Code:
db = new dbConnection(server, database, user, password);
stmnt1 = db.newStatement("Select user, password FROM user WHERE id = ? LIMIT 1");
stmnt2 = db.newStatement("UPDATE user SET username=? WHERE id=?");
stmnt3 = db.newStatement("Select user, password FROM user WHERE id > ?);

result = db.execute(stmnt1, 7); //Rückgabe als assoziatives Array
result2 = db.execute(stmnt2, "blabla", 8); //Rückgabe: affected rows
result3 = db.execute(stmnt3, 7); //Rückgabe als assoziatives Array von Objekten
Es sollte ja kein Problem für die Klasse sein, den Typ eines SQL Querys einfach zu bestimen. Je nach Rückgabe könnte man wunderbar entweder Erfolg / Fehler, anzahl der geänderten Reihen, etc zurückgeben. Bei SELECT Anweisungen können die zurückgegebenen Objekte gleich noch die richtigen Datentypen aufweisen. Toll wäre auch man übergibt noch nen STring mit attr="feld1, feld2, feld3" welcher dann zur Benennung der assoziativen Arrays verwendet wird.
Gibts so eine Lösung? (Bitte, bitte ja^^) Oder muss ich da wirklich selbst Hand anlegen?
-------------------
Hier gleich noch alles auf was ich bisher gestoßen bin, was mir aber nicht zugesagt hat ;-)
http://static.springsource.org/spring/docs/2.0.x/reference/jdbc.html - Das genannte Sprin Framework, bin ich grad nochmal am durchlesen, ebenso die dbutils
http://www.theserverside.com/tt/articles/article.tss?l=SQLExecutor - Ganz nett, aber auch nicht meins
http://www.javaworld.com/javaworld/jw-05-2002/jw-0524-sql.html - Klingt vielversprechend, hab aber keine praktische Dokumentation gefunden
http://www.ibm.com/developerworks/java/library/j-jdbcwrap/ - Nett, einfach, sieht aber schwer unperformant aus
http://www.oop-reserch.com/simple_dao.html - Gerade am lesen, sieht bisher seeehr interessant aus
 
Zuletzt bearbeitet:
So, schlussendlich hab ich doch selbst Hand angelegt, dafür ist es nun so wie ich es mir gewünscht hab ;-) (Fast zumindest, ein Assoziatives Multidimensionales Array ist in Java ja mit schwerer Tipparbeit verbunden).
Was haltet ihr von der Klasse?
Code:
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
public class MyQuery {
	static Connection con = null;	//Global Connection
	static Statement smt = null;	//Global Statement
	
	Connection localCon = null;		//Local Connection
	Statement localSmt = null;		//Local Statement
	PreparedStatement localPrepSmt;	//Prepared Statement
	String attr = null;				//Column names for Output
	ResultSet erg = null;			//Result Set
	ResultSetMetaData meta = null;	//Stores Meta Data
	int rowCount;					//rowCount for UPDATE/INSERT/DELETE Querys
	char type;						//Typ der Anweisung
	/******************************************************* ESTABLISH GLOBAL CONNECTION */
	public static void globalConnection(String server, String user, String pwd, String database){
		try {
			Class.forName( "com.mysql.jdbc.Driver" ); //Load Driver
		}
		catch ( ClassNotFoundException e ) {
			e.printStackTrace();
			System.exit(1);
		}
		try {
			con = DriverManager.getConnection("jdbc:mysql://"+server+"/"+database, user, pwd);
			smt = con.createStatement();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	/******************************************************* ESTABLISH LOCAL CONNECTION */
	public void localConnection(String server, String user, String pwd, String database){
		try {
			localCon = DriverManager.getConnection("jdbc:mysql://"+server+"/"+database, user, pwd);
			localSmt = localCon.createStatement();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	/******************************************************* CONSTRUCTOR TO BUILD PREPARED STATEMENT */
	public MyQuery(String query){ this(query, null); }
	public MyQuery(String query, String attr) {
		//Use Global Connection first
		localCon = con;
		localSmt = smt;
		try {
			localPrepSmt = con.prepareStatement(query);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.attr = attr;
		if(query.startsWith("SELECT")) type = 'S';
		else if(query.startsWith("UPDATE")) type = 'U';
		else if(query.startsWith("DELETE")) type = 'D';
		else type = 'I';
	}
	/******************************************************* EXECUTE PREPARED STATEMENT */
	public HashMap<String, ArrayList<Object>> execute(Object ...rest){
		HashMap<String, ArrayList<Object>> result = null;
		try{
			//Alle übergebenen Objekte in das Prepared Statement schreiben
			for (int i = 0; i < rest.length; i++) {
				if(rest[i] != null) localPrepSmt.setObject(i+1, rest[i]); //Setzt den Parameter, wenn null: lassen wie bisher
			}
			if(type == 'S'){
				erg = localPrepSmt.executeQuery(); //SELECT Query Results
				result = parse(erg);
				
				
			} else if(type == 'U' || type == 'I' || type == 'D'){
				rowCount = localPrepSmt.executeUpdate(); //UPDATE/INSERT/DELETE Query Rowcount
				System.out.println(rowCount);
				
			}
		} catch (SQLException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		
		return result;
	}
	/******************************************************* EXECUTE INSTANT STATEMENT */
	public static Object instantExecute(String query, String attr){
		try {
			smt.execute(query);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
	private HashMap<String, ArrayList<Object>> parse(ResultSet r){ return parse(r, null); }
	private HashMap<String, ArrayList<Object>> parse(ResultSet r, String attr){
		int i=0;
		HashMap<String, ArrayList<Object>> result = new HashMap<String, ArrayList<Object>>();
		
		try {
			
			//Wenn der attr-String nicht gesetzt ist selbst zusammenbasteln
			if(attr == null){
				meta = r.getMetaData();
				int cols = meta.getColumnCount();
				attr = "";
				for (i=1; i <= cols; i++) {
					attr += ","+meta.getColumnName(i);
				}
				attr = attr.substring(1);
			}
			//2D Array erstellen
			String[] colNames = attr.split(",");
			for (i = 0; i < colNames.length; i++) {
				result.put(colNames[i], new ArrayList<Object>());
			}
			//Mit Inhalt füllen
			while(r.next()){
				for (i=0; i < colNames.length; i++) {
					ArrayList<Object> list = result.get(colNames[i]);
					list.add( r.getObject(i+1) );
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return result;
	}
}
Wie man sieht
a) ist sie noch nicht fertig
b) bin ich Java Anfänger
c) übergehe ich da einiges an guten Javapraktiken ;-)
Alles in allem Funktioniert ein Beispielaufruf dann so:
Code:
MyQuery.globalConnection("localhost", "user", "pass", "database");
MyQuery.globalConnection("localhost", "root", "", "teamjump");

MyQuery query1 = new MyQuery("SELECT * FROM user WHERE id=? AND name=? LIMIT 1");
result = query1.execute(1, "testname");
System.out.println(result.get("pwd").get(0));
Irgendjemand Vorschläge was ich besser machen könnte?
Außer dem bisher noch nicht wirklich fertigen Error Handling?

Marius
 
Genau das was du hier zeigst ist das Problem wenn mans selber schreibt. Man muss schon höllisch aufpassen alle Verbindung wieder korrekt zu schließen. Dir fehlen ein haufen finally Blöcke zum schließen von statements und resultsets. Das ist alles nicht ganz trivial wenn man später nicht irgendwann in Probleme laufen will dass die Datenbank aufgrund zuvieler offener Verbindungen gar nicht mehr reagiert.

Bei deiner execute Methode sehe ich das Problem, dass du den Zusammenhang zwischen den Daten einer Zeile nur sehr locker über den Index in der ArrayList hast. Das ist eigentlich auch eine Sache die man nicht machen sollte. Meiner Ansicht nach wäre eine ArrayList<Map<String,Object>> sinnvoller.

Aber für einen Anfänger ist einmal selber schreiben sicher gar nicht schlecht ;)
 
Danke für die Tips, Fehlerbehandlung ist wie gesagt noch unfertig, aber den Rest schau ich mir mal an. Ist gut, dass du das geschrieben hast, ich muss mir halt alles über irgendwelche Quellen zusammenfrickeln und bau halt nur das ein von dem ich gehört hab :-)
Und selber schreiben finde ich auch gar nicht schlecht, hab auch damals mit funfury.de angefangen und konnte kaum programmieren, jetzt ist es ein voll funktionsfähiges Browserspiel mit allem drum und dran.
 

Neue Beiträge

Zurück