Exklusiver Zugriff auf Datensatz in einer PortgreSQL-Datenbank

MScalli

Erfahrenes Mitglied
Hi.

Ich versuche schon ewig in Java einen Datensatz 'Exklusiv' zu lesen und bei zugriff auf einen bereits exklusiv geöffneten Datensatz eine Meldung zu bringen.. z.B.
DIeser Datensatz ist von User XY Exklusiv geöffnet!.
(Wobei der sperrende User hier sehrt wichtig ist)

Habe schon die verschiedensten Sachen ausprobiert(bis jetzt nur was auf SQL-Ebene gefunden) aber irgendwie komm ich nicht auf eine Lösung.

Damit ihr wisst wie ich es bis jetzt versucht habe poste ich mal einen meiner Versuche.
Einen Datensatz mit SELECT FOR UPDATE öffnen.
Das funktioniert soweit, aber bei einem weiteren zugriff habe ich 2 Probleme.
a: ich komme nicht an den sperrenden User
b: es soll bei zugriff auf einen gesperrten Satz SOFORT die Nachricht kommen 'Datensatz wird gerade von User XY' bearbeitet, zugriff nicht möglich' oder so ähnlich :)

plz Help.
Hier bisschen quellcode der soweit funktioniert.

Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import javax.swing.JOptionPane;


public class DatenbankTest {
	
	private Connection con = null;
    private Statement stmt;
	
	public DatenbankTest(){
		System.out.println("START");
		
		// Verbinden mit DB
	    try {
		      Class.forName ("org.postgresql.Driver");
		    } catch (ClassNotFoundException e) {
		      e.printStackTrace ();
		      System.exit (1);
		    }
		    // Verbindung mit der Datenbank herstellen
		    try{

		      con = DriverManager.getConnection ("jdbc:postgresql:" + "//" + 
		    		  "SRV" + ":" + 		// Host
		    		  "5432" + "/"+ 		// Port
		    		  "MyDB" ,			// Database
		    		  "postgres", 			// User
		    		  "passwort");		// password

	    } catch (SQLException e) {
	      e.printStackTrace ();
	      System.exit (1);
	    }
		    
			
		 try {
			con.setAutoCommit(false);
			stmt = con.createStatement();

			// Datensatz exklusiv öffnen
			stmt.executeQuery("SELECT * FROM hallo WHERE id = '90' FOR UPDATE NOWAIT");

			// Wird die JOptionPane angezeigt ist der Datensatz im Exklusiven zugriff.
			// ein UPDATE auf genau diesen Datensatz ist nicht mehr möglich
	 		JOptionPane.showInputDialog("UPDATE NOWAIT") ;

	 		con.commit();
		 }
		 catch(SQLException ex) {
			 System.out.println(ex);
		 }
		 
		 System.out.println("ENDE");
	}

	public static void main(String[] args) {
		new DatenbankTest();

	}

}

Bitte schaut es euch mal an denn ich komm nicht auf die Lösung :(

Gruss
MScalli
 
Willst du das ganze auf der Javaeben Lösen oder auf der Datenbankebene?

Auf der Javaebene, könntest du eine Map anlegen.
Als Key hinterlegts du dort die den Primary Key des Datensatzes wenn jemand ihn öffnet. Als Value den User der Ihn geöffnet hat.

Wenn nun nochjemand auf diesen Datendatensatz zugreifen möchte, schaust du erst ob die ID in der Map hinterlegt ist. Ist das der Fall, kannst du die Meldung geben und den Username dafür aus der Map auslesen.

Aber bevor du das so umsetzt, warte erst auf Kommentare von anderen Usern.
Ich weiß nicht ob bei diesem Lösungsansatz sichergestellt ist, dass wirklich immer nur einer auf einen Datensatz zugreifen kann. Auf alle Fälle müssten die beiden Methoden zum eintragen (und natürlich auch wieder austragen, wenn der User fertig ist) in /aus der Map sehr durchdacht sein (threadsicher etc.)
 
ich wollte erst auf java ebene lösen, leider gibt es da mehrere probleme.
Das grösste das ich gerade sehe ist wenn etwas unvorhergesehenes geschieht, z.B. ein Programmabsturz bleibt der Eintrag ja bestehen.
(ich hätte Tabelle, ID und User in einer Tabelle gespeichert da das Programm ja von mehreren Usern benutzt wird)

Auf Datenbank-Ebene hätte ich das Problem nicht.
Ich müsste eigentlich 'nur' wissen ist der Satz gesperrt und wenn ja von wem.

leider ist es bei meinem Programm so wenn der Satz gesperrt wird und ich von woanderst einen UPDATE machen will das ich nicht SOFORT weiss das dieser gesperrt ist sondern das Programm einfach wartet mit dem UPDATE.
Sobald ich bei dem geposteten Prog die JOptionPane schliesse wird das andere Programm ausgeführt.

Es müsste aber so sein das bei dem Versuch eines UPDATES auf einen gesperrten Satz SOFORT wissen muss das dieser gerade nicht verändert werden kann, dies dem User mittels PopUp sage und (ganz wichtig) ihm auch sage wer diesen Exklusiven zugriff gerade macht.
 
Also irgendwie bekomme ich es nicht hin!!

Die Probleme gehen schon los wenn ich den Datensatz sperre und jetzt über ein anderes Programm versuche den selben satz zu verändern..
Das ist nicht möglich, wie es ja gewollt ist, ABER ...
Das Prog läuft dann einfach nicht weiter und bleibt solange stehen bis ich die sperre aufhebe.
Ich komm einfach nicht drauf wie ich meinem Prog sagen kann, du der Satz ist gesperrt, bring eine meldung und gut ist.

Es kommt ja keine exception denn es ist ja eigentlich kein fehler!!

:confused:
 
Moin,

...
Das Prog läuft dann einfach nicht weiter und bleibt solange stehen bis ich die sperre aufhebe...
Ja das ist das normale Verhalten. Damit Du eine "Rückmeldung" von der DB bekommst,
selektiere den Datensatz mit SELECT FOR UPDATE NOWAIT - das sorgt dafür, dass der Client der auf den gesperrten Satz zugreifen will, eine entsprechende Exception bekommt, die Du dann in deiner Anwendung abhandeln kannst.

Grüße
THMD
 
GENAU DAS IST ES.
Wenn ein 2ter User auch einen SELECT .. FOR UPDATE NOWAIT absetzt bekommt er(endlich) eine Exception.
Ich habe mich glaub noch nie über eine Exception so gefreut wie heute^^

Ich hoffe nur ich habs richtig verstanden, denn ich habe mir mit
Java:
System.out.println(ex.getErrorCode());
den ErrorCode geholt(war 0) und kann jetzt eigentlich in der Exception abfragen
Java:
if(x.getErrorCode()==0){
   System.out.println("Satz ist gesperrt");
}

Ich hoffe nur 0 ist der richtige ErrorCode da er eigentlich nur aussagt das dieser Satz nicht gesperrt werden kann..
was in meinem Fall ja aussagt das er schon gesperrt ist.
Oder!
 
Zurück