2016-06-05 15 views
2

Ich habe ein Beispiel SpringBoot Projekt erstellt und JPA Repository für Persistent einfache Gruß Objekt in der Datenbank (Greeting Id und Gruß Text). Ich habe hinzugefügt @Transactional annotaion zu createGreeting() Methode in Service-Klasse GreetingServiceImpl und werfen eine RuntimeException nach Gruß Datensatz in der Datenbank beibehalten wird. Ich werde den Greeting Record außer Kraft setzen in der Datenbank rolleback. Aber der Datensatz existiert noch in der Datenbank. Code unten angegeben. Irgendwelche Vorschläge? Danke im Voraus.Spring Boot und Spring Daten JPA @Transactional Not Working

Anwendung

@SpringBootApplication 
@EnableTransactionManagement 
public class SpringBootDataWebApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(SpringBootDataWebApplication.class, args); 
    } 
} 

ServletInitializer

public class ServletInitializer extends SpringBootServletInitializer { 

     @Override 
     protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 
      return application.sources(SpringBootDataWebApplication.class); 
     } 

    } 

Modell

@Entity 
public class Greeting { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String text; 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getText() { 
     return text; 
    } 

    public void setText(String text) { 
     this.text = text; 
    } 

} 

Ruhe-Controller

@RestController 
public class GreetingController { 

    @Autowired 
    private GreetingService greetingService; 

    @RequestMapping(value = "/api/greetings", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) 
    public ResponseEntity<Greeting> createGreeting(@RequestBody Greeting greeting) throws Exception { 
     Greeting greetingCreated = greetingService.createGreeting(greeting); 
     return new ResponseEntity<>(greetingCreated, HttpStatus.CREATED); 
    } 

} 

Service Class

@Service 
public class GreetingServiceImpl implements GreetingService { 

    @Autowired 
    private GreetingRepository greetingRepository; 

    @Override 
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false) 
    public Greeting createGreeting(Greeting greeting) { 
     if (greeting.getId() != null) 
      return null; 
     Greeting greetingCreated = greetingRepository.save(greeting); 
     if (true) { 
      throw new RuntimeException("Roll me back!"); 
     } 
     return greetingCreated; 
    } 

} 

Repository

@Repository 
public interface GreetingRepository extends JpaRepository<Greeting, Long> { 

} 

POM Datei:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.sam</groupId> 
    <artifactId>spring</artifactId> 
    <version>1.0</version> 
    <packaging>war</packaging> 

    <name>SpringBootDataWeb</name> 
    <description>Demo project for Spring Boot and Spring Data</description> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.3.5.RELEASE</version> 
     <relativePath /> <!-- lookup parent from repository --> 
    </parent> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <java.version>1.8</java.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-jpa</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <scope>runtime</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.hsqldb</groupId> 
      <artifactId>hsqldb</artifactId> 
      <scope>runtime</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-tomcat</artifactId> 
      <scope>provided</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-jta-atomikos</artifactId> 
     </dependency> 
    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
     </plugins> 
    </build> 


</project> 

ERROR MESSAGE

{ 
    "timestamp": 1465094495762, 
    "status": 500, 
    "error": "Internal Server Error", 
    "exception": "java.lang.RuntimeException", 
    "message": "Roll me back!", 
    "path": "/SpringBootDataWeb/api/greetings" 
} 
+0

Ich habe Ihr Setup getestet und es funktioniert wie Sie erwarten - Transaktion wird zurückgesetzt, nichts wird in DB gespeichert. Vielleicht solltest du ein [mcve] in Form eines GitHub-Projekts erstellen. – Roman

+0

Verwenden Sie zufällig MySQL mit [MyISAM engine] (http://dev.mysql.com/doc/refman/5.5/en/myisam-storage-engine.html)? Ich frage, weil es Transaktionen nicht unterstützt. – Roman

+0

Ja Roman, ich benutze MySQL. –

Antwort

0

auf hoher Ebene ist JpaTransactionManager zu greetingRepository.save(greeting) gebunden.

Wenn es irgendein eine Ausnahme innerhalb der Methode aufgetreten sparen würde ein Rollback tut, wird JpaTransactionManagercommit ausgeführt werden, wenn keine Ausnahme während save und TransactionStatus werden completed eingestellt werden.

So post-commit, wenn es eine Ausnahme gibt in Anwendungscode nicht an JpaTransactionManager gebunden ist eine Anwendungsausnahme.

+0

Aber ich möchte Transaktion von Service-Klasse verwalten. Wie kann ich das erreichen? –

0

Idealerweise wird das Zurückrollen während des Unit/Integration Tests durchgeführt. Und während dieser Szenarien wird die Annotation @TransactionConfiguration(defaultRollback = true) über die Klasse verwendet, in der Testfälle geschrieben werden.

Können Sie dies in Ihrer Serviceklasse ausprobieren?

+0

@TransactionConfiguration (defaultRollback = true) Annotation ist veraltet SriKanta. –

0

Mehr Dinge im Auge zu haben:

  • Die @Repository Anmerkung nicht necesary ist da Ihre Repository-Schnittstelle bereits ab JpaRepository erstreckt.
  • Ihre Service-Implementierung fehlt (oder ist zumindest im obigen Beispiel) eine @Service Annotation, so dass die @Autowired in der Steuerung nicht funktionieren sollte (ich nehme an, Sie haben es in der Schnittstelle? Da Sie Bean nicht verwandt sind Ausnahmen).
  • Die @Transactional auf der Methode Stand ist korrekt, obwohl standardmäßig es readOnly=false setzt, so dass Sie es nicht wieder

Was ich denke, ist, dass Ihr Gruß Einheit möglicherweise nicht korrekt abgebildet angeben müssen , ist aber immer noch schwer zu erraten mit der angezeigten Fehlermeldung. Könnten Sie mehr Informationen zum Fehler StackTrace geben?

+0

Danke für die Punkte. Den Code finden Sie unter github url. Ich habe @service Annotation im Code deklariert, aber beim Kopieren habe ich es versäumt. https://github.com/SandeepGoud0612/SpringBootDataWeb.git –

+0

Nebenbei habe ich Web Application Project (War Packaging) erstellt. Ich benutze JBoss Wildfly und Mysql. –

Verwandte Themen