2017-01-09 1 views
2

Ich möchte JavaFX mit DB-Zugriff mit Spring JDBC verwenden. Aber ich bin ganz neu zum Frühling und es scheint, dass ich nicht ganz verstehe es Funktionen, vor allem Transaktionen Kosten ...JavaFX + Spring (JDBC & @ SpringBootApplication & @ Autowired & @Transactional)

Ich habe folgende Abhängigkeiten zu meinem Projekt hinzugefügt:

compile 'org.springframework.boot:spring-boot-starter-jdbc' 
runtime 'mysql:mysql-connector-java' 

... und Ich möchte den Spring-Transaktions-Mechanismus verwenden, wenn die GUI-Anwendung ihre Operationen auf der DB ausführt. Wie ich es verstehe, folgenden Code sollte:

  • initialize und JavaFX-Anwendung starten - erstellen und zeigen GUI Drahtgitter-
  • initialisieren Frühling
  • konfigurieren und JdbcTemplate Abhängigkeit
  • Starttransaktion zur Bearbeitung injizieren und beginnen Transaktion
  • Verwenden Sie das jdbcTemplate-Objekt, um 5 Einträge im DB in for loop
  • zu erstellen, simulieren Sie Fehler (durch Werfen RuntimeException)
  • revert Operationen auf DB
  • Ausfahrt

Also, zusammenfassend: wenn RuntimeException in Methode geworfen wird als @Transactional mit Anmerkungen versehen, die alle Einträge bereits mit dieser Methode erstellt zurückkehren sollte vor der Anwendung beendet wird, nicht wahr?

Alle erstellten Einträge bleiben jedoch dauerhaft in der DB (ich kann sie dort sehen, nachdem die Anwendung beendet wurde). Also zuerst - verstehe ich richtig, wie diese Transaktionen funktionieren sollten? Wenn ja, wie kann ich dann funktionieren, wie ich es erwarte?

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.context.ConfigurableApplicationContext; 
import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.transaction.annotation.Transactional; 

import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.List; 


@SpringBootApplication 
public class SpringTransactional extends Application { 
    private Pane viewPane; 

    private ConfigurableApplicationContext springContext; 

    /** application.properties: 
    spring.datasource.driver-class-name = com.mysql.jdbc.Driver 
    spring.datasource.url = jdbc:mysql://localhost:3306/db_name?useSSL=false&serverTimezone=UTC 
    spring.datasource.username = db_username 
    spring.datasource.password = username123 
    */ 
    @Autowired 
    private JdbcTemplate jdbcTemplate; 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void init() throws Exception { 
     springContext = SpringApplication.run(SpringTransactional.class); 
     springContext.getAutowireCapableBeanFactory().autowireBean(this); 
    } 

    @Override 
    public void stop() throws Exception { 
     springContext.close(); 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     viewPane = assembleView(primaryStage); 

     try { 
      db_transaction_test(); 
     } catch (RuntimeException e) { 
      e.printStackTrace(); 
     } 

     Platform.exit(); 
    } 

    private Pane assembleView(Stage primaryStage) { 
     VBox rootPane = new VBox(); 
     rootPane.setSpacing(10); 
     rootPane.setPadding(new Insets(10)); 
     rootPane.setStyle("-fx-base: #84a7ad;"); 
     rootPane.getChildren().add(new Label("GUI goes here.")); 

     primaryStage.setScene(new Scene(rootPane)); 
     primaryStage.setResizable(false); 
     primaryStage.show(); 

     return rootPane; 
    } 

    @Transactional 
    private void db_transaction_test() { 
     for (int i = 0; i < 10; i++) { 
      try { 
       int entry_name = getEntryId("entry_" + i); 
       System.out.println("Created entry id=" + entry_name); 
      } catch (DaoException e) { 
       e.printStackTrace(); 
      } 

      if (i == 5) { 
       throw new RuntimeException("Testing data upload procedure break."); 
      } 
     } 
    } 

    /** DB creation and schema: 
    CREATE DATABASE db_name; 
    CREATE USER db_username; 

    USE db_name; 
    GRANT ALL ON db_name.* TO db_username; 

    SET PASSWORD FOR spz = PASSWORD('username123'); 
    FLUSH PRIVILEGES; 

    CREATE TABLE Entry (
    entry_ID INT NOT NULL AUTO_INCREMENT, 
    name TEXT NOT NULL, 

    PRIMARY KEY (entry_ID) 
    ); 
    */ 
    private int getEntryId(String entryName) throws DaoException { 
     List<DbEntry> dbEntries = retrieveEntriesFor(entryName); 

     if (dbEntries.size() == 1) { 
      return dbEntries.get(0).getEntry_ID(); 
     } else if (dbEntries.size() == 0) { 
      String sqlInsert = "INSERT INTO Entry (name) VALUES (?)"; 
      jdbcTemplate.update(sqlInsert, entryName); 
      dbEntries = retrieveEntriesFor(entryName); 
      if (dbEntries.size() == 1) { 
       return dbEntries.get(0).getEntry_ID(); 
      } else { 
       throw new DaoException("Invalid results amount received after creating new (" + dbEntries.size() + ") when getting entry for name: " + entryName); 
      } 
     } else { 
      throw new DaoException("Invalid results amount received (" + dbEntries.size() + ") when getting entry for name: " + entryName); 
     } 
    } 

    private List<DbEntry> retrieveEntriesFor(String entryName) { 
     return jdbcTemplate.query("SELECT * FROM Entry WHERE name=?;", (ResultSet result, int rowNum) -> unMarshal(result), entryName); 
    } 

    private DbEntry unMarshal(ResultSet result) throws SQLException { 
     DbEntry dbEntry = new DbEntry(); 
     dbEntry.setEntry_ID(result.getInt("entry_ID")); 
     dbEntry.setName(result.getString("name")); 
     return dbEntry; 
    } 

    public class DbEntry { 
     private int entry_ID; 
     private String name; 

     int getEntry_ID() { return entry_ID; } 
     void setEntry_ID(int entry_ID) { this.entry_ID = entry_ID; } 
     public String getName() { return name; } 
     public void setName(String name) { this.name = name; } 
    } 

    private class DaoException extends Throwable { 
     DaoException(String err_msg) { super(err_msg); } 
    } 
} 

Antwort

0

Nach weiteren Tests, dass getrennte Federkomponente EntryDao Werke (dank James_D) zu schaffen scheint, aber nur, wenn db_transaction_test annotaded mit @Transactional in dh Klasse - OPTION A im Code unten.

Aber was mich wirklich interessiert, ist OPTION B - wenn db_transaction_test mit @Transactional in einer anderen Klasse notiert ist. Dies liegt daran, dass die DAO-Klasse nicht über DB-nicht realisierte Probleme informiert ist (und dies auch nicht tun sollte), die den Grund für das Zurücksetzen einer Reihe früherer DB-Vorgänge darstellen. Diese Informationen stammen von anderen "Controllern", deren Fehler nicht zu Datenintegritätsproblemen führen dürfen. Also im Beispiel unten SpringTransactional sollte der einzige sein, der diese spezielle RuntimeException("Testing data upload procedure break."); werfen kann (als Beispiel für reale System-/Umweltprobleme). Wie Stacktrack am Ende jedoch zeigt - Transaktion ist dort nicht initialisiert.

So gibt es eine Möglichkeit, es funktioniert zu bekommen, wie ich mit Spring @Transactional (aka. Deklarative Transaktionen) oder nur mit manuellen (aka. Programmatischen) Spring-Transaktionen-Kontrolle brauche? Und wenn das die einzige Möglichkeit ist, wie konfiguriert man DataSourceTransactionManager mit @SpringBootApplication für "Auto-Konfiguration" und @Autowired für jdbcTemplate Objekt?

Hauptklasse:

package tmp; 

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.context.ConfigurableApplicationContext; 
import org.springframework.transaction.annotation.Transactional; 
import tmp.dao.EntryDao; 


@SpringBootApplication 
public class SpringTransactional extends Application { 
    private Pane viewPane; 

    private ConfigurableApplicationContext springContext; 

    @Autowired 
    private EntryDao dao; 

    public static void main(String[] args) { launch(args); } 

    @Override 
    public void init() throws Exception { 
     springContext = SpringApplication.run(SpringTransactional.class); 
     springContext.getAutowireCapableBeanFactory().autowireBean(this); 
    } 

    @Override 
    public void stop() throws Exception { springContext.close(); } 

    @Override 
    public void start(Stage primaryStage) { 
     viewPane = assembleView(primaryStage); 

     // OPTION A: 
     try { 
      dao.db_transaction_test(); 
     } catch (RuntimeException e) { 
      e.printStackTrace(); 
     } 

     // OPTION B: 
     try { 
      db_transaction_test(); 
     } catch (RuntimeException e) { 
      e.printStackTrace(); 
     } 

     Platform.exit(); 
    } 

    @Transactional 
    private void db_transaction_test() { 
     for (int i = 0; i < 10; i++) { 
      try { 
       int entry_name = dao.getEntryId("entry_" + i); 
       System.out.println("Created entry id=" + entry_name); 
      } catch (EntryDao.DaoException e) { 
       e.printStackTrace(); 
      } 

      if (i == 5) { 
       throw new RuntimeException("Testing data upload procedure break."); 
      } 
     } 
    } 

    private Pane assembleView(Stage primaryStage) { 
     VBox rootPane = new VBox(); 
     rootPane.setSpacing(10); 
     rootPane.setPadding(new Insets(10)); 
     rootPane.setStyle("-fx-base: #84a7ad;"); 
     rootPane.getChildren().add(new Label("GUI goes here.")); 

     primaryStage.setScene(new Scene(rootPane)); 
     primaryStage.setResizable(false); 
     primaryStage.show(); 

     return rootPane; 
    } 
} 

EntryDao Klasse:

package tmp.dao; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.stereotype.Component; 
import org.springframework.transaction.annotation.Transactional; 

import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.List; 

/** 
* DB creation and schema: 
* CREATE DATABASE db_name; 
* CREATE USER db_username; 
* <p> 
* USE db_name; 
* GRANT ALL ON db_name.* TO db_username; 
* <p> 
* SET PASSWORD FOR spz = PASSWORD('username123'); 
* FLUSH PRIVILEGES; 
* <p> 
* CREATE TABLE Entry (
* entry_ID INT NOT NULL AUTO_INCREMENT, 
* name TEXT NOT NULL, 
* <p> 
* PRIMARY KEY (entry_ID) 
*); 
*/ 
@Component 
public class EntryDao { 
    /** 
    * application.properties: 
    * spring.datasource.driver-class-name = com.mysql.jdbc.Driver 
    * spring.datasource.url = jdbc:mysql://localhost:3306/db_name?useSSL=false&serverTimezone=UTC 
    * spring.datasource.username = db_username 
    * spring.datasource.password = username123 
    */ 
    @Autowired 
    private JdbcTemplate jdbcTemplate; 

    @Transactional 
    public void db_transaction_test() { 
     for (int i = 0; i < 10; i++) { 
      try { 
       int entry_name = getEntryId("entry_" + i); 
       System.out.println("Created entry id=" + entry_name); 
      } catch (EntryDao.DaoException e) { 
       e.printStackTrace(); 
      } 

      if (i == 5) { 
       throw new RuntimeException("Testing data upload procedure break."); 
      } 
     } 
    } 

    public int getEntryId(String entryName) throws DaoException { 
     List<DbEntry> dbEntries = retrieveEntriesFor(entryName); 

     if (dbEntries.size() == 1) { 
      return dbEntries.get(0).getEntry_ID(); 
     } else if (dbEntries.size() == 0) { 
      String sqlInsert = "INSERT INTO Entry (name) VALUES (?)"; 
      jdbcTemplate.update(sqlInsert, entryName); 
      dbEntries = retrieveEntriesFor(entryName); 
      if (dbEntries.size() == 1) { 
       return dbEntries.get(0).getEntry_ID(); 
      } else { 
       throw new DaoException("Invalid results amount received after creating new (" + dbEntries.size() + ") when getting entry for name: " + entryName); 
      } 
     } else { 
      throw new DaoException("Invalid results amount received (" + dbEntries.size() + ") when getting entry for name: " + entryName); 
     } 
    } 

    private List<DbEntry> retrieveEntriesFor(String entryName) { 
     return jdbcTemplate.query("SELECT * FROM Entry WHERE name=?;", (ResultSet result, int rowNum) -> unMarshal(result), entryName); 
    } 

    private DbEntry unMarshal(ResultSet result) throws SQLException { 
     DbEntry dbEntry = new DbEntry(); 
     dbEntry.setEntry_ID(result.getInt("entry_ID")); 
     dbEntry.setName(result.getString("name")); 
     return dbEntry; 
    } 

    public class DbEntry { 
     private int entry_ID; 
     private String name; 

     int getEntry_ID() { return entry_ID; } 
     void setEntry_ID(int entry_ID) { this.entry_ID = entry_ID; } 
     public String getName() { return name; } 
     public void setName(String name) { this.name = name; } 
    } 

    public class DaoException extends Throwable { DaoException(String err_msg) { super(err_msg); } } 
} 

STACKTRACE

. ____   _   __ _ _ 
/\\/___'_ __ _ _(_)_ __ __ _ \ \ \ \ 
(()\___ | '_ | '_| | '_ \/ _` | \ \ \ \ 
\\/ ___)| |_)| | | | | || (_| | )))) 
    ' |____| .__|_| |_|_| |_\__, |//// 
=========|_|==============|___/=/_/_/_/ 
:: Spring Boot ::  (v1.4.3.RELEASE) 

2017-01-10 09:41:48.902 INFO 1860 --- [JavaFX-Launcher] o.s.boot.SpringApplication    : Starting application on alwihasolaptop with PID 1860 (started by alwi in C:\alwi\Workspace_SPZ\GCodeClient) 
2017-01-10 09:41:48.905 INFO 1860 --- [JavaFX-Launcher] o.s.boot.SpringApplication    : No active profile set, falling back to default profiles: default 
2017-01-10 09:41:48.965 INFO 1860 --- [JavaFX-Launcher] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]18660f3: startup date [Tue Jan 10 09:41:48 CET 2017]; root of context hierarchy 
2017-01-10 09:41:49.917 INFO 1860 --- [JavaFX-Launcher] o.s.j.e.a.AnnotationMBeanExporter  : Registering beans for JMX exposure on startup 
2017-01-10 09:41:49.927 INFO 1860 --- [JavaFX-Launcher] o.s.boot.SpringApplication    : Started application in 1.384 seconds (JVM running for 1.969) 
Created entry id=73 
Created entry id=74 
Created entry id=75 
Created entry id=76 
Created entry id=77 
Created entry id=78 
java.lang.RuntimeException: Testing data upload procedure break. 
    at tmp.dao.EntryDao.db_transaction_test(EntryDao.java:53) 
    at tmp.dao.EntryDao$$FastClassBySpringCGLIB$$a857b433.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) 
    at tmp.dao.EntryDao$$EnhancerBySpringCGLIB$$84e8651e.db_transaction_test(<generated>) 
    at tmp.SpringTransactional.start(SpringTransactional.java:45) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863) 
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326) 
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294) 
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) 
    at java.lang.Thread.run(Thread.java:745) 
Created entry id=73 
Created entry id=74 
Created entry id=75 
Created entry id=76 
Created entry id=77 
Created entry id=78 
2017-01-10 09:41:50.545 INFO 1860 --- [lication Thread] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]18660f3: startup date [Tue Jan 10 09:41:48 CET 2017]; root of context hierarchy 
java.lang.RuntimeException: Testing data upload procedure break. 
    at tmp.SpringTransactional.db_transaction_test(SpringTransactional.java:71) 
    at tmp.SpringTransactional.start(SpringTransactional.java:52) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863) 
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326) 
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294) 
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) 
    at java.lang.Thread.run(Thread.java:745) 
2017-01-10 09:41:50.546 INFO 1860 --- [lication Thread] o.s.j.e.a.AnnotationMBeanExporter  : Unregistering JMX-exposed beans on shutdown 

Process finished with exit code 0 

LÖSUNG:

beste Lösung, die ich bis jetzt gefunden habe, so ist mit Spring TransactionTemplate zusammen mit weiteren Callback-Klasse:

package tmp.dao; 

public abstract class DbTransactionTask { public abstract void executeTask(); } 

und in SpringTransactional Klasse db_transaction_test() Methode (beachten Sie, dass @Transactional ist out):

private void db_transaction_test() { 
    DbTransactionTask dbTask = new DbTransactionTask() { 
     @Override 
     public void executeTask() { 
      for (int i = 0; i < 10; i++) { 
       try { 
        int entry_name = dao.getEntryId("entry_" + i); 
        System.out.println("Created entry id=" + entry_name); 
       } catch (EntryDao.DaoException e) { 
        e.printStackTrace(); 
       } 

       if (i == 5) { 
        throw new RuntimeException("Testing data upload procedure break."); 
       } 
      } 
     } 
    }; 

    dao.executeTransactionWithoutResult(dbTask); 
} 

EntryDao Klasse benötigt diese zusätzlichen Code:

@Autowired 
private TransactionTemplate transactionTemplate; 

public void executeTransactionWithoutResult(DbTransactionTask dbTask) { 
    transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
     @Override 
     protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { 
      dbTask.executeTask(); 
     } 
    }); 
} 
+0

Das typische Setup besteht also darin, dass Sie Transaktionen auf Ihren Business-Tier-Methoden markieren und Ihr DAO in die Business-Schicht einfügen, deren Methoden es dann aufrufen. Aber die tatsächliche Antwort auf Ihre Frage ist dieselbe, egal wie Sie sie strukturieren: '@ Transactional' * funktioniert nur mit Spring-Beans *. In Ihrer Frage haben Sie versucht, es für ein Objekt zu verwenden, das extern für Spring erstellt wurde. –

+0

Und was ist mit: 'springContext.getAutowireCapableBeanFactory(). AutowireBean (this);' in der Frage? Es war in der Lage, '@Autowired private JdbcTemplate jdbcTemplate;' obwohl es "auf einem Objekt, das extern zu Spring erstellt wurde", wie Sie es ... – alwi

+0

Richtig: das im Grunde sagt der Anwendungskontext, alle bekannten Bohnen in Felder mit Anmerkungen zu injizieren '@ Autowire' für das übergebene Objekt (in diesem Fall). Aber es kann dieses Objekt im Speicher tatsächlich nicht durch ein Proxy-Objekt ersetzen. Während also Beans injiziert wird, kann das Verhalten des vorhandenen Objekts nicht geändert werden. Also macht Ihre 'db_transaction_test()' Methode immer noch genau das, wofür Sie sie programmiert haben, nicht mehr und nicht weniger. Es kann die Implementierung einer Methode, die zu einem vorhandenen Objekt gehört, mit dem Transaktionsverhalten nicht magisch verzieren. –

4

Transaktionen im Frühjahr auf die gleiche Weise arbeiten, wie AOP im Frühjahr arbeitet: Wenn Sie eine Bohne von Spring anfordern, die Methoden markiert als Transaktions hat, den Sie tatsächlich einen Proxy zu diesem Bean, deren Umsetzung der Transaktions Methoden „erhalten ziert "Die Implementierung, die Sie in Ihrer Implementierungsklasse bereitstellen. Kurz gesagt, die Implementierung der Methode in der Proxy-Klasse beginnt mit einer Transaktion, ruft dann die in Ihrer Implementierungsklasse definierte Methode auf und schreibt die Transaktion entweder zurück oder rollt sie zurück.

So Ich denke das Problem ist, dass die SpringTransactional Instanz nicht von dem Spring-Anwendungskontext erstellt wird, sondern wird durch den JavaFX Startvorgang erstellt (das heißt es wird von dem JavaFX Rahmen erstellt, wenn Sie Application.launch() nennen). Daher kann Spring das Proxyobjekt nicht erstellen, das das Transaktionsverhalten implementiert.

Versuchen Sie, die Datenbankfunktionalität in eine separate Klasse einzuteilen, die im Frühjahr verwaltet wird, und eine Instanz davon in Ihre Anwendungsklasse zu injizieren. I.e.so etwas wie

// Note: I'm only familiar with "traditional" Spring, not Spring boot. 
// Not sure if this annotation is picked up by Spring boot, you may need to 
// make some changes to the config or something to get this working. 
@Component 
public class DAO { 

    @Autowired 
    private JdbcTemplate jdbcTemplate ; 

    @Transactional 
    private void db_transaction_test() { 
     // ... 
    } 

    // ... 
} 

und dann in Ihrer Anwendungsklasse:

@SpringBootApplication 
public class SpringTransactional extends Application { 
    private Pane viewPane; 

    private ConfigurableApplicationContext springContext; 

    @Autowired 
    private DAO dao ; 

    // ... 

    @Override 
    public void start(Stage primaryStage) { 
     viewPane = assembleView(primaryStage); 

     try { 
      dao.db_transaction_test(); 
     } catch (RuntimeException e) { 
      e.printStackTrace(); 
     } 

     Platform.exit(); 
    } 

    // ... 
} 
+0

Hallo und Danke für die Antwort, aber wie ich oben erwähnt habe, bin ich völlig neu in Spring und wollte eine Lösung, ohne die ganze "alte" Art zu lernen iguration (mit eigenen Ausgaben) und damit - wie im Thema - mit '@ SpringBootApplication' ist einer der Hauptteile dieser Frage und was mich wirklich interessiert ... – alwi

+0

@alwi Ich glaube, Sie haben den Punkt hier völlig verpasst . Die oben stehenden '// ...' sollen nur anzeigen, dass Sie den vorhandenen Code einschließen, d. H., Dass dieser noch Spring Boot verwendet. Sie müssen das DAO nur als Spring-Managed-Bean konfigurieren (dies geschieht jedoch im Spring Boot). Nirgends in meiner Antwort sage ich "Spring Spring nicht benutzen". Der Punkt ist, dass '@ Transactional' * nur mit Spring-Beans funktioniert *: Es funktioniert nicht magisch, wenn Sie es für Methoden in Objekten verwenden, die extern von Spring erstellt wurden (ob Spring Spring oder" classic "Spring Framework)). –

+0

Ich verstehe was du sagst. Es ist offensichtlich, dass // ... die ganze Geschäftslogik bedeutet.In der vorherigen Nachricht bezog ich mich auf Ihren Kommentar "Sie können einige Änderungen an der Konfiguration vornehmen oder etwas, um dies zum Funktionieren zu bringen" zusammen mit "Ich bin nur vertraut mit/traditionellen/Spring, nicht Spring Boot.". – alwi