2016-06-05 4 views
2

Я создал образец проекта SpringBoot и используя JPA Репозиторий для сохранения простого приветственного объекта в базе данных (Greeting Id и приветственного текста). Я добавил @Transactional annotaion в метод createGreeting() в классе обслуживания GreetingServiceImpl и выбрасывает RuntimeException после записи приветствия в базе данных. Я исключаю, что запись приветствия будет свернута в базе данных. Но запись все еще существует в базе данных. Код приведен ниже. Какие-либо предложения? Заранее спасибо.Весна и весна Данные JPA @Transactional Не работает

Применение

@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); 
     } 

    } 

Модель

@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; 
    } 

} 

Rest Контроллер

@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 
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 Файл:

<?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> 

ОШИБКА СООБЩЕНИЕ

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

Я протестировал вашу настройку и работает так, как вы ожидаете - транзакция откатывается, ничего не сохраняется в БД. Возможно, вы должны создать [mcve] в форме проекта github. – Roman

+0

Вы, случайно, используете MySQL с [MyISAM engine] (http://dev.mysql.com/doc/refman/5.5/en/myisam-storage-engine.html)? Я спрашиваю, потому что он не поддерживает транзакции. – Roman

+0

Да, Roman, я использую MySQL. –

ответ

0

на высоком уровне JpaTransactionManager связан с greetingRepository.save(greeting).

Если любые любое исключение произошло внутри метода экономии будет делать откат, JpaTransactionManager выполнит commit если не исключение при save и TransactionStatus будут установлены в completed.

Таким образом, сообщение должно быть зафиксировано, если в коде приложения не было какого-либо исключения, не связанного с JpaTransactionManager является исключением приложения.

+0

Но я хочу управлять транзакцией из класса Service. Как я могу это достичь? –

0

Идеально откат выполняется во время тестирования единицы измерения/интеграции. И во время этих сценариев аннотация @TransactionConfiguration(defaultRollback = true) используется над классом, где записываются тестовые примеры.

Вы можете попробовать это в своем классе обслуживания.

+0

@TransactionConfiguration (defaultRollback = true) аннотация устарела SriKanta. –

0

Несколько вещей, чтобы иметь в виду:

  • @Repository аннотаций не necesary, так как ваш интерфейс хранилища уже простирается от JpaRepository.
  • Ваша реализация реализации отсутствует (или, по крайней мере, не приведена в примере выше) аннотация @Service, поэтому @Autowired в контроллере не должен работать (предположим, у вас есть это в интерфейсе? Поскольку у вас нет связанных с bean-компонентами исключения).
  • @Transactional на уровне метода является правильным, хотя по умолчанию он устанавливает readOnly=false, так что вам не нужно указывать его снова

То, что я имею в виду, что ваше приветствие лицо не может быть корректно отображаться , но до сих пор сложно догадаться с отображаемым сообщением об ошибке. Не могли бы вы предоставить дополнительную информацию об ошибке stacktrace?

+0

Спасибо за баллы. Пожалуйста, найдите код ниже github url. У меня есть @service Аннотации, объявленные в коде, но я пропустил, пока копирует пасту. https://github.com/SandeepGoud0612/SpringBootDataWeb.git –

+0

Кстати, я создал проект веб-приложений (War Packaging). Я использую JBoss Wildfly и Mysql. –

Смежные вопросы