# (JavaFX 8) SQLite Datenbank in einem TableView darstellen



## cw.java (2. Apr 2015)

Hallo Community,

ich habe ein Programm geschrieben was mir anhand von Werten eine XML erstellt die dann von einem Mounter verarbeitet  werden kann. Die angelegten Jobs werden in einer Datenbank die auf XML basiert gespeichert. Das Programm läuft und funktioniert so wie es soll, in der Version liegt kein Problem vor.

Nun habe ich mich entschieden das Programm so auf zu bauen das keine XML sondern eine SQLite Datenbank zum speichern der Jobs verwendet werden soll. Muss aber dazu sagen das ich zuvor noch nie etwas mit SQL oder MySQL zu tun hatte. Wobei ich mich aber auch schon etwas in dieses Thema eingelesen habe, gibt ja genügend Material darüber.

Das Problem was ich habe ist, das ich gerne den Inhalt der SQLite Datenbank in einem TableView darstellen will was kein Problem sein sollte den dafür ist es ja da. Wie gesagt in der XML Version funktioniert das alles.

Die Datenbank habe ich angelegt und ich kann auch schon auf die Daten zugreifen. 

Hier ein Auszug aus dem Terminal von Eclipse:

ID = 1
Job ID = 9150001
Job Name = Test1
Cliche Manufacturer = Reproflex
Number of stereotypes = 2
Delay = 0.4
Range = 1341.0
Working width = 2500.0

ID = 2
Job ID = 9150002
Job Name = Test 2
Cliche Manufacturer = Stichnote
Number of stereotypes = 1
Delay = 0.4
Range = 1100.0
Working width = 2500.0

Diese Daten gibt mir das Terminal aus wenn ich die Daten per SELECT Anweisung abfrage was auch richtig ist.
Nun kommt aber mein Problem wenn ich das ganze im TableView ausgeben will, dann wird mir nur der zweite Datensatz dargestellt und das auch noch doppelt. Ich bin mir nicht ganz sicher was da das Problem ist!!! 
Im Terminal werden mir die Datensätze alle ausgegeben, was muss ich machen wenn ich die Datensätze richtig im TableView darstellen will?

Wäre super nett wenn ihr mir da mal ein Hinweis zu geben könntet!!!

Hier noch der Code zu den Klassen:

MainApp

```
public class MainApp extends Application {
	
	private Stage primaryStage;
	private BorderPane rootLayout;

	@Override
	public void start(Stage primaryStage) {
		this.primaryStage = primaryStage;
		this.primaryStage.setTitle("KoordinatenRechner");
		
		initRootLayout();
		
		showCalculatorView();
	}
	
	/**
	 * Initializes the root layout.
	 */
	public void initRootLayout() {
		try {
			// Load root layout from fxml file.
			FXMLLoader loader = new FXMLLoader();
			loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
			rootLayout = (BorderPane) loader.load();
			
			// Show the scene containing the root layout.
			Scene scene = new Scene(rootLayout);
			primaryStage.setScene(scene);
			
			// Give the controller access to the main app.
			
			primaryStage.show();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Shows the CalculatorView inside the root layout.
	 */
	public void showCalculatorView() {
		try {
			// Load CalculatorView from fxml file.
			FXMLLoader loader = new FXMLLoader();
			loader.setLocation(MainApp.class.getResource("view/CalculatorView.fxml"));
			AnchorPane calculatorView = (AnchorPane) loader.load();
			
			// Set CalculatorView into the center of root layout.
			rootLayout.setCenter(calculatorView);
			
			// Give the controller access to the main app.
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
	
	/**
	 * Return the main Stage.
	 * @return
	 */
	public Stage getPrimaryStage() {
		return primaryStage;
	}
}
```

Model Class Job

```
public class Job {

	private SimpleIntegerProperty id;
	private SimpleStringProperty jobID;
	private SimpleStringProperty jobName;
	private SimpleStringProperty clicheManufacturer;
	private SimpleIntegerProperty numberOfSterotypes;
	private SimpleDoubleProperty delay;
	private SimpleDoubleProperty range;
	private SimpleDoubleProperty workingWidth;
	
	/**
	 * Default constructor
	 */
	public Job() {
		this(null, null);
	}
	
	/**
	 * Constructor with some initial data.
	 * 
	 * @param jobID
	 * @param jobName
	 */
	public Job(String jobID, String jobName) {
		this.id = new SimpleIntegerProperty();
		this.jobID = new SimpleStringProperty();
		this.jobName = new SimpleStringProperty();
		
		this.clicheManufacturer = new SimpleStringProperty();
		this.numberOfSterotypes = new SimpleIntegerProperty();
		this.delay = new SimpleDoubleProperty();
		this.range = new SimpleDoubleProperty();
		this.workingWidth = new SimpleDoubleProperty();
	}
	
	/**
	 * 
	 * @return
	 */
	public int getID() {
		return id.get();
	}

	/**
	 * @return the id
	 */
	public IntegerProperty IDProperty() {
		return id;
	}
	
	/**
	 * 
	 * @param id
	 */
	public void setID(int id) {
        this.id.set(id);
    }
	
	/**
	 * 
	 * @return
	 */
	public String getJobID() {
		return jobID.get();
	}

	/**
	 * @return the jobID
	 */
	public StringProperty JobIDProperty() {
		return jobID;
	}
	
	/**
	 * 
	 * @param jobID
	 */
	public void setJobID(String jobID) {
        this.jobID.set(jobID);
    }
	
	/**
	 * 
	 * @return
	 */
	public String getJobName() {
		return jobName.get();
	}

	/**
	 * @return the jobName
	 */
	public StringProperty JobNameProperty() {
		return jobName;
	}
	
	/**
	 * 
	 * @param jobName
	 */
	public void setJobName(String jobName) {
        this.jobName.set(jobName);
    }
	
	/**
	 * 
	 * @return
	 */
	public String getClicheManufacturer() {
		return clicheManufacturer.get();
	}

	/**
	 * @return the clicheManufacturer
	 */
	public StringProperty ClicheManufacturerProperty() {
		return clicheManufacturer;
	}
	
	/**
	 * 
	 * @param clicheManufacturer
	 */
	public void setClicheManufacturer(String clicheManufacturer) {
        this.clicheManufacturer.set(clicheManufacturer);
    }
	
	/**
	 * 
	 * @return
	 */
	public int getNumberOfSterotypes() {
		return numberOfSterotypes.get();
	}

	/**
	 * @return the numberOfSterotypes
	 */
	public IntegerProperty NumberOfSterotypesProperty() {
		return numberOfSterotypes;
	}
	
	/**
	 * 
	 * @param numberOfSterotypes
	 */
	public void setNumberOfSterotypes(int numberOfSterotypes) {
        this.numberOfSterotypes.set(numberOfSterotypes);
    }
	
	/**
	 * 
	 * @return
	 */
	public double getDelay() {
		return delay.get();
	}

	/**
	 * @return the delay
	 */
	public DoubleProperty DelayProperty() {
		return delay;
	}
	
	/**
	 * 
	 * @param delay
	 */
	public void setDelay(double delay) {
        this.delay.set(delay);
    }
	
	/**
	 * 
	 * @return
	 */
	public double getRange() {
		return range.get();
	}

	/**
	 * @return the range
	 */
	public DoubleProperty RangeProperty() {
		return range;
	}
	
	/**
	 * 
	 * @param range
	 */
	public void setRange(double range) {
        this.range.set(range);
    }
	
	/**
	 * 
	 * @return
	 */
	public double getWorkingWidth() {
		return workingWidth.get();
	}

	/**
	 * @return the workingWidth
	 */
	public DoubleProperty WorkingWidthProperty() {
		return workingWidth;
	}
	
	/**
	 * 
	 * @param workingWidth
	 */
	public void setWorkingWidth(double workingWidth) {
        this.workingWidth.set(workingWidth);
    }
}
```

Controller Class


```
public class CalculatorViewController {
	
	@FXML
	private TableView<Job> tableView;
	@FXML
	private TableColumn<Job, Number> idColumn;
	@FXML
	private TableColumn<Job, String> jobIDColumn;
	@FXML
	private TableColumn<Job, String> jobNameColumn;
	
	private ObservableList<Job> masterData = FXCollections.observableArrayList();
	
	private MainApp mainApp;
	private Job job;
	
	@FXML   
	private void initialize() {
		buildMasterData();
		
		// Initialize the job table with the two columns.
		idColumn.setCellValueFactory(cellData -> cellData.getValue().IDProperty());
    	jobIDColumn.setCellValueFactory(cellData -> cellData.getValue().JobIDProperty());
    	jobNameColumn.setCellValueFactory(cellData -> cellData.getValue().JobNameProperty());
		
	}
	
	public void buildMasterData() {
		Job job = new Job();
		Connection c = null;
	    Statement stmt = null;
	    try {
		      Class.forName("org.sqlite.JDBC");
		      c = DriverManager.getConnection("jdbc:sqlite:KRDB.db");
		      c.setAutoCommit(false);

		      stmt = c.createStatement();
		      ResultSet rs = stmt.executeQuery( "SELECT * FROM Jobs;" );
		      while ( rs.next() ) {
		         int id = rs.getInt("ID");
		         String  jobID = rs.getString("Job ID");
		         String jobName  = rs.getString("Job Name");
		         String clicheManufacturer = rs.getString("ClicheManufacturer");
		         int numberOfStereotypes = rs.getInt("Number of stereotypes");
		         double delay = rs.getDouble("Delay");
		         double range = rs.getDouble("Range");
		         double workingWidth = rs.getDouble("Working width");
		         job.setID(id);
		         job.setJobID(jobID);
		         job.setJobName(jobName);
		         job.setClicheManufacturer(clicheManufacturer);
		         job.setNumberOfSterotypes(numberOfStereotypes);
		         job.setDelay(delay);
		         job.setRange(range);
		         job.setWorkingWidth(workingWidth);
		         System.out.println( "ID = " + id );
		         System.out.println( "Job ID = " + jobID );
		         System.out.println( "Job Name = " + jobName );
		         System.out.println( "Cliche Manufacturer = " + clicheManufacturer );
		         System.out.println( "Number of stereotypes = " + numberOfStereotypes );
		         System.out.println( "Delay = " + delay );
		         System.out.println( "Range = " + range );
		         System.out.println( "Working width = " + workingWidth );
		         System.out.println();
		         
		         
		         masterData.addAll(job);
		         tableView.setItems(masterData);
		      }
		      rs.close();
		      stmt.close();
		      c.close();
		    } catch ( Exception e ) {
		      System.err.println( e.getClass().getName() + ": " + e.getMessage() );
		      System.exit(0);
		    }
	}
	
	/**
	 * Is called by the main application to give a reference back to itself.
	 * @param mainApp
	 */
	public void setMainApp(MainApp mainApp) {
		this.mainApp = mainApp;
	}

}
```

Ich denke mal nicht das ihr die FXML files auch braucht.

Und hier noch ein Screenshot wo man sieht das nur der letzte Datensatz angezeigt wird und das auch noch doppelt.



Ich hoffe ihr könnt mir Helfen

mfg
cw.java


----------



## Ruzmanz (2. Apr 2015)

Du hast wahrscheinlich 2 Datensätze in deiner DB ... Zuerst solltest du job als Instanzvariable rauswerfen. Anschließend packst du den lokalen Job in die Schleife, denn pro Schleifendurchlauf musst du ein neues Job-Objekt erstellen. 

Falsch:

```
public class CalculatorViewController {	
	private ObservableList<Job> masterData = FXCollections.observableArrayList();
	private Job job; // Löschen!

	public void buildMasterData() {
		Job job = new Job(); // Es gibt exakt EINEN Job, dessen Parameter später geändert werden.
		Connection c = null;
	    Statement stmt = null;
	    try {
		      while ( rs.next() ) {
		         int id = rs.getInt("ID");
		         job.setID(id);		         
		         masterData.addAll(job);
		         tableView.setItems(masterData);
		      }
            }
	}
}
```

Evtl. richtig:


```
public class CalculatorViewController {	
	private ObservableList<Job> masterData = FXCollections.observableArrayList();

	public void buildMasterData() {
		Connection c = null;
	    Statement stmt = null;
	    try {
		      while ( rs.next() ) {
		       Job job = new Job();
		         int id = rs.getInt("ID");
		         job.setID(id);		         
		         masterData.addAll(job);
		         tableView.setItems(masterData);
		      }
            }
	}
}
```

Verbesserungspotential:
- buildMasterData scheint privat zu sein.
- Anstatt masterData.addAll(job); müsste es masterData.add(job); lauten
- tableView.setItems(masterData); könnte man in initalize einmal setzen


----------



## cw.java (3. Apr 2015)

Hey Ruzmanz,

du hast natürlich vollkommen recht das die Instanzvariable "job" weg muss weil sie nicht benötigt wird. Das hatte ich übersehen das die noch da ist. Sorry das war mein Fehler. 

Ich habe den Code jetzt korrigiert und nun funktioniert es so wie es soll wobei der Hauptfehler darin lag das ich das "Job job = new Job();"
einfach am falschen Punkt gesetzt habe so wie ich das machen wollte . 

Vielen dank für den Tipp das hat mir sehr geholfen

Hier nun noch mal der Korrigierte Code für alle anderen den es vielleicht auch Helfen kann.


```
public class CalculatorViewController {
	
	@FXML
	private TableView<Job> tableView;
	@FXML
	private TableColumn<Job, Number> idColumn;
	@FXML
	private TableColumn<Job, String> jobIDColumn;
	@FXML
	private TableColumn<Job, String> jobNameColumn;
	
	private ObservableList<Job> masterData = FXCollections.observableArrayList();
	
	private MainApp mainApp;
	
	@FXML   
	private void initialize() {
		buildMasterData();
		
		// Initialize the job table with the two columns.
		idColumn.setCellValueFactory(cellData -> cellData.getValue().IDProperty());
    	jobIDColumn.setCellValueFactory(cellData -> cellData.getValue().JobIDProperty());
    	jobNameColumn.setCellValueFactory(cellData -> cellData.getValue().JobNameProperty());
		
    	tableView.setItems(masterData);
	}
	
	public void buildMasterData() {
		Connection c = null;
	    Statement stmt = null;
	    try {
		      Class.forName("org.sqlite.JDBC");
		      c = DriverManager.getConnection("jdbc:sqlite:KRDB.db");
		      c.setAutoCommit(false);

		      stmt = c.createStatement();
		      ResultSet rs = stmt.executeQuery( "SELECT * FROM Jobs;" );
		      while ( rs.next() ) {
		    	  Job job = new Job();
		    	 int id = rs.getInt("ID");
		         String  jobID = rs.getString("Job ID");
		         String jobName  = rs.getString("Job Name");
		         job.setID(id);
		         job.setJobID(jobID);
		         job.setJobName(jobName);
		         
		         
		         masterData.add(job);
		         
		      }
		      rs.close();
		      stmt.close();
		      c.close();
		    } catch ( Exception e ) {
		      System.err.println( e.getClass().getName() + ": " + e.getMessage() );
		      System.exit(0);
		    }
	}
	
	/**
	 * Is called by the main application to give a reference back to itself.
	 * @param mainApp
	 */
	public void setMainApp(MainApp mainApp) {
		this.mainApp = mainApp;
	}

}
```

mfg
cw.java


----------

