Datenbank bei Klassenverteilung führt zu NullPointerException

Ich bitte um einen Denkanstoß bei einem Anfängerproblem. Ich hoffe, ihr könnt mir helfen. Ich sitz schon den ganzen Tag und durchstöber das Web.

Problem:
Verteilung von Driver, Connection, Statement und Resultset auf verschiedene Klassen. Wenn alles in der Klasse db_connection ist, funktioniert es, aber bei der Verteilung nicht. Ich denk mal, dass das Problem bei der Vererbung liegt, denn db_resultset müsste wohl auch von db_connection erben. Dies ist natürlich nicht möglich.

Fehlermeldung: NullPointerexception.

Exception in thread "main" Verbindung hergestellt
java.lang.NullPointerException
at Datenhaltung.db_statements.db_createStatement(db_statements.java:27)
at Datenhaltung.dbMain.main(dbMain.java:20)



[JAVA=42]
public class db_connection {

private String dbHostname = "***";
private String dbPort ="1521";
private String dbName = "***";
private String dbUser = "***";
private String dbPassword = "**";
private Connection conn = null;

public Connection getConn() {
return conn;
}

public void setConn(Connection conn) {
this.conn = conn;
}



public Connection db_connect ()
{

try {
System.out.println("* Verbindung aufbauen");
String url = "jdbc😱racle:thin😡"+dbHostname+":"+dbPort+":"+dbName;
conn = DriverManager.getConnection(url, dbUser, dbPassword);
System.out.println("Verbindung hergestellt");
// conn.setAutoCommit(false);
}


catch (SQLException sqlconnect)
{
System.out.println("SQLException: " + sqlconnect.getMessage());
System.out.println("SQLState: " + sqlconnect.getSQLState());
System.out.println("VendorError: " + sqlconnect.getErrorCode());
sqlconnect.printStackTrace();
}
return conn;
}


public void db_close()
{
System.out.println("* Datenbank-Verbindung beenden");
try
{
conn.close();
System.out.println("Verbindung geschlossen");
}

catch (SQLException sqlclose)
{
System.out.println("SQLException: " + sqlclose.getMessage());
System.out.println("SQLState: " + sqlclose.getSQLState());
System.out.println("VendorError: " + sqlclose.getErrorCode());
sqlclose.printStackTrace();
}
}


[/code]

Die Verbindung wird hergestellt und geschlossen, wenn nur die klasse db_connection und driver genutzt wird.


[JAVA=42]
public class db_statements extends db_connection {

private Statement stmt = null;

public Statement getStmt() {
return stmt;
}

public void setStmt(Statement stmt) {
this.stmt = stmt;
}

public Statement db_createStatement()
{

try {
stmt = getConn().createStatement();
} catch (SQLException e) {
e.printStackTrace();
}

return stmt;
}


public void db_closeStatement ()
{
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

[/code]

Ich denke, es ist sinnvoll, eine eigene Klasse für die Statements zu erstellen. Hatte diese vorher auch bei der Connection, find es aber aufgeteilt schöner.

[JAVA=42]
public class db_resultsets extends db_statements{

public void resultNames()
{
try {
ResultSet kunden = getStmt().executeQuery("SELECT * FROM kunde");
while (kunden.next())
{
String name = kunden.getString("Name");
System.out.println(name);
}
}

catch (SQLException rsetNamen)
{
rsetNamen.printStackTrace();
}



}



}

[/code]



[JAVA=42]
public class db_driver {

public void db_registerDriver()
{

try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
System.out.println("Treiber geladen");



} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


[/code]

Hier noch die Main...
[JAVA=42]
public class dbMain {

/**
* @param args
*/
public static void main(String[] args) {

//Klassen erzeugen
db_driver dbdriver = new db_driver();
db_connection dbconn = new db_connection();
db_statements dbstmt = new db_statements();
db_resultsets dbrset = new db_resultsets();


dbdriver.db_registerDriver();
dbconn.db_connect();
dbstmt.db_createStatement();

dbrset.resultNames();

dbstmt.db_closeStatement();
dbconn.db_close();
}

}


[/code]
 
Zuletzt bearbeitet:
[c]stmt = getConn().createStatement();[/c]

[c]getConn()[/c] liefert [c]null[/c], weil du zuvor keine Verbindung mit [c]db_connect ()[/c] aufgebaut hast.

Edit:

Außerdem ist dein Aufbau sehr seltsam.

[c]public class db_statements extends db_connection {[/c]

Ein Statement braucht eine Connection, ist aber keine Connection.

[c]public class db_resultsets extends db_statements{[/c]

Hier genauso. Ein Statement liefert ein Resultset zurück, ein Resultset ist aber kein Statement.


Du solltest dir nochmal den Unterschied zwischen Vererbung und Aggregation klar machen.
 
Zuletzt bearbeitet:
Danke für die schnelle Antwort!

Vererbung war hier echt nicht gerade die Superidee...
Über die Umsetzung der Aggregation muss ich auch noch einiges lesen, genauso wie Interfaces...
Die Beziehungen sind zumindest soweit klar.

Spricht was dagegen, dass conn und stmt static sind? Pro Sitzung werden diese einmal aufgerufen. Ich habe das jetzt einfach so verändert...
conn und stmt static
Code:
stmt = db_connection.getConn().createStatement();
beim Resultset natürlich auch.
Die extends natürlich raus. Es ist jetzt zumindest lauffähig, obwohl unelegant.

Nachdem ich dann die Exception-Behandlung fertig habe, werd ich mich nochmal ransetzen.
Ich hoffe, die Fragen sind nicht zu sehr Noob und ich werde hier nicht rausgeschmissen, wenn nochmal sowas kommt.
 
Statisch sollte man weitestgehend vermeiden. Wenn man unbedingt nur genau eine Ausprägung einer Klasse zulassen will, dann nutzt man das Singleton-Pattern*.

Ansonsten macht man sich eigentlich nur unnötige Probleme damit.




* Führt hier vermutlich zu weit, aber ganz kurz gesagt: Eine ganz normale Klasse, die aber einen privaten Konstruktor hat und eine statische Methode, die beim ersten Aufruf eine Instanz anlegt und zurück gibt und bei weiteren Aufrufen die schon angelegte Instanz zurück gibt.
 
Glaubenssache, static kann bie sachen die Programmweit static sind auch benutzt werden. Problem dabei in diesem fall ist jedoch, dass du nicht sicherstellen kannst das auch wirklich die variable immer Inhalt hat egal an welcher stelle man sie aufruft (macht bei größeren programmen dann probleme wenn man sowas vergisst)
 
Danke erstmal für die Infos!
Static scheint wohl nicht wirklich elegant zu sein...
Assoziationen umzusetzen werde ich wohl später versuchen, in UML ist das iwie leichter.
Eine Möglichkeit wäre noch Instanzen von den einzelnen Klassen zu erzeugen, was ich mir auch erspare. Ich habe wieder alles in eine Klasse gepackt und es läuft soweit.

Jetzt habe ich ein neues Problem mit dem ich absolut nicht weiterkomme!
Das resultset in einer Hashmap zu speichern, bei der der Key die Kundennummer ist. Ich verstehe das Prinzip scheinbar nicht! Ich hab schon so viel gegoogelt, aber keine Chance.

Ich hab mir folgendes überlegt...
Java:
    public HashMap<String, Customer> getAllCustomers() //throws Exception
    {
    	HashMap<String, Customer> customerResult = new HashMap<String, Customer>();
    	String queryGetCustomers = "SELECT customerNr, customerTitle, customerName, customerFirstname, customerStreet, customerStreetNr, customerPostcode, customerCity FROM customer ORDER BY customerNr ASC";
    	
    	try 
    	 {
    		 ResultSet rset = stmt.executeQuery(queryGetCustomers);    		 
    		 Customer customer = new Customer();
    		 while (rset.next())
    		 {    			 

    			 // Zugriff auf die höhere Schicht!!!!! ALARM!!
    			 
    		
    			 
    			 customer.setCustomerNr(rset.getString("customerNr"));
    			 customerResult.put(customer.getCustomerNr(), customer);
    			 
    			 customer.setCustomerTitle(rset.getString("customerTitle"));
    			 customerResult.put(customer.getCustomerNr(), customer);
//    			 customerResult.put(customer.getCustomerTitle(), customer);
    			 
    			 customer.setCustomerName(rset.getString("customerName"));
    			 customerResult.put(customer.getCustomerNr(), customer);
//    			 customerResult.put(customer.getCustomerName(), customer);
    			 
    			 customer.setCustomerFirstname(rset.getString("customerFirstname"));
    			 customerResult.put(customer.getCustomerNr(), customer);
//    			 customerResult.put(customer.getCustomerFirstname(), customer);
    			 
    			 customer.setCustomerStreet(rset.getString("customerStreet"));
    			 customerResult.put(customer.getCustomerNr(), customer);
//    			 customerResult.put(customer.getCustomerStreet(), customer);
    			 
    			 customer.setCustomerStreetNr(rset.getString("customerStreetNr"));
    			 customerResult.put(customer.getCustomerNr(), customer);
//    			 customerResult.put(customer.getCustomerStreetNr(), customer);
    			    			 
    			 customer.setCustomerPostcode(rset.getString("customerPostcode"));
    			 customerResult.put(customer.getCustomerNr(), customer);
//    			 customerResult.put(customer.getCustomerPostcode(), customer);
    			 
    			 customer.setCustomerCity(rset.getString("customerCity"));
    			 customerResult.put(customer.getCustomerNr(), customer);
//    			 customerResult.put(customer.getCustomerCity(), customer);
    		 }
    			 return customerResult;
... + Exception...

Dann versuche ich das in einer gui in eine Tabelle zu schreiben:
Java:
public Object getValueAt(int row, int col)  
	{	
		return tableData.entrySet().toArray()[row]; // tableData ist customerResult aus der oberen klasse. Sonst nehm ich da auch keySet()...
	}

Ausgabe:
- So: In jeder Zeile wird nur der Key angezeigt, je Zeile immer der Gleiche, also 3 3 3 3 3 ...
- Die // hab ich vorher probiert, da standen halt die richtigen Daten drin, nur je Zeile immer der Gleiche, also vorname vorname vorname...



Probleme:
- Alle Daten haben den gleichen Key!

Fragen:
- Muss ich eine neue Hashmap mit einem Int customerNr erstellen oder geht das auch so?
- Wie kann ich jedem Kunden eine eigenen Key zuweisen? (warum geht das mit customerNr nicht?)
- Was läuft hier allgemein falsch?
 
Zuletzt bearbeitet:
Hallo rushinsquirrel,

Danke erstmal für die Infos!

Probleme:
- Alle Daten haben den gleichen Key!

ich würde eher tippen, dass jeder Key 8 Mal vorkommt.

Fragen:
- Muss ich eine neue Hashmap mit einem Int customerNr erstellen oder geht das auch so?
- Wie kann ich jedem Kunden eine eigenen Key zuweisen? (warum geht das mit customerNr nicht?)
- Was läuft hier allgemein falsch?

zu 1)
Nein, es geht auch so.

zu 2) und 3)
Es reicht völlig, wenn Du das Customer-Objekt an die HashMap hängst, nachdem Du
alle Felder eingelesen hast. Du machst das hier nach jedem eingelesenen Feld. ;-)

Ich hoffe, ich konnte Dir weiterhelfen.

VG ROlf
 
Danke Rolf,
klingt irgendwie logisch... Ich habe jetzt einfach dem Customer die Werte zugeordnet und ihn am Ende der Hashmap hinzugefügt.

Habe heute erfahren, dass es keine gute Idee ist, die Kunden in einer HashMap zu speichern. Hab jetzt einen Vector genommen und diesen dann in den JTable eingetragen. Funktioniert soweit und ich bin begeistert.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben