2016-08-23 132 views
0

我有包含兩個方法的RestController:彈簧引導+的WebSocket +踐踏+ JPA:不即使@Transactional註釋插入的數據

  1. 方法beat1與@MessageMapping註釋以接收所述消息的WebSocket(在STOMP協議)從客戶端
  2. 方法beat2與@RequestMapping註釋爲接收來自客戶端的HTTP請求

這兩種方法具有內部相同的代碼:

@RestController 
@RequestMapping("/api/member") 
@MessageMapping("member") 
public class MemberCtrl 
{ 
    @MessageMapping("beat") 
    public Heartbeat beat1(@Payload Heartbeat heartbeat) 
    { 
    return memberService.beat(heartbeat); 
    } 

    @RequestMapping(value = "/beat", method = RequestMethod.POST) 
    public Heartbeat beat2(@RequestBody Heartbeat heartbeat) 
    { 
    return memberService.beat(heartbeat); 
    } 
} 

memberService僅僅是包含業務邏輯,這將做一個數據庫中的數據插入和春天JPARepository正常的春季服務:

@Service 
public class MemberServiceImpl implements MemberService, UserDetailsService 
{ 

    @Autowired 
    private HeartbeatRepository heartbeatRepository; 

    @Transactional 
    @Override 
    public Heartbeat beat(Heartbeat heartbeat) 
    { 
     heartbeat = heartbeatRepository.save(heartbeat); 
     return heartbeat; 
    } 
} 

至於我HeartbeatRepository的代碼:

@Repository 
public interface HeatbeatRepository extends JpaRepository<Heartbeat, Integer> 
{ 

} 

這是我的問題:

  1. 當我用websocket發送STOMP消息時,控制器中的beat1方法會執行,但是沒有數據被插入數據庫表中。

  2. 當我發送一個http請求時,控制器中的beat2方法被執行,Heartbeat域對象被成功地插入到數據庫表中。

我執行的WebSocket,所以我需要的是讓beat1作品,我其實不需要beat2可言。 (beat2只是用於測試)

由於兩個beat1beat2方法調用同一個服務方法memberSevicebeat2的作品,我覺得我的執行MemberServiceHeartbeatRepository都沒有問題。

由於FOT休眠的日誌每個beat1beat2

  1. baat1僅打印SQL用於獲取下一個ID,我沒有看到插入和事務中的SQL承諾:

    2016-08-23 18:32:56.227 DEBUG 43874 --- [nboundChannel-4] org.hibernate.SQL      : select nextval ('heartbeat_id_seq') 
    2016-08-23 18:32:56.227 DEBUG 43874 --- [nboundChannel-4] o.h.e.j.internal.LogicalConnectionImpl : Obtaining JDBC connection 
    2016-08-23 18:32:56.242 DEBUG 43874 --- [nboundChannel-4] o.h.e.j.internal.LogicalConnectionImpl : Obtained JDBC connection 
    2016-08-23 18:32:56.261 DEBUG 43874 --- [nboundChannel-4] org.hibernate.id.SequenceGenerator  : Sequence identifier generated: BasicHolder[java.lang.Integer[20]] 
    2016-08-23 18:32:56.261 DEBUG 43874 --- [nboundChannel-4] o.h.e.i.AbstractSaveEventListener  : Generated identifier: 20, using strategy: org.hibernate.id.SequenceHiLoGenerator 
    2016-08-23 18:32:56.266 DEBUG 43874 --- [nboundChannel-4] o.h.e.j.internal.LogicalConnectionImpl : Releasing JDBC connection 
    2016-08-23 18:32:56.266 DEBUG 43874 --- [nboundChannel-4] o.h.e.j.internal.LogicalConnectionImpl : Released JDBC connection 
    

2. beat2確實打印完成的insetaion SQL並提交事務,所以這就是爲什麼它成功做插入到數據庫表:

2016-08-23 18:20:29.937 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.t.spi.AbstractTransactionImpl  : begin 
2016-08-23 18:20:29.937 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.j.internal.LogicalConnectionImpl : Obtaining JDBC connection 
2016-08-23 18:20:29.951 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.j.internal.LogicalConnectionImpl : Obtained JDBC connection 
2016-08-23 18:20:29.951 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.t.internal.jdbc.JdbcTransaction : initial autocommit status: true 
2016-08-23 18:20:29.951 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.t.internal.jdbc.JdbcTransaction : disabling autocommit 
2016-08-23 18:20:29.966 DEBUG 43846 --- [nio-8989-exec-9] org.hibernate.SQL      : select nextval ('heartbeat_id_seq') 
2016-08-23 18:20:29.986 DEBUG 43846 --- [nio-8989-exec-9] org.hibernate.id.SequenceGenerator  : Sequence identifier generated: BasicHolder[java.lang.Integer[19]] 
2016-08-23 18:20:29.986 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.i.AbstractSaveEventListener  : Generated identifier: 19, using strategy: org.hibernate.id.SequenceHiLoGenerator 
2016-08-23 18:20:29.992 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.t.spi.AbstractTransactionImpl  : committing 
2016-08-23 18:20:29.993 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.i.AbstractFlushingEventListener : Processing flush-time cascades 
2016-08-23 18:20:29.993 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.i.AbstractFlushingEventListener : Dirty checking collections 
2016-08-23 18:20:29.995 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.i.AbstractFlushingEventListener : Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects 
2016-08-23 18:20:29.995 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.i.AbstractFlushingEventListener : Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections 
2016-08-23 18:20:29.996 DEBUG 43846 --- [nio-8989-exec-9] o.hibernate.internal.util.EntityPrinter : Listing entities: 
2016-08-23 18:20:29.998 DEBUG 43846 --- [nio-8989-exec-9] o.hibernate.internal.util.EntityPrinter : com.yamk.api.domain.orm.Heartbeat{lifespanSec=0, lostedSec=0, lastHeartbeatTime=Tue Aug 23 18:19:35 UTC 2016, createdTime=Tue Aug 23 18:20:29 UTC 2016, location=POINT (121.56818389892578 25.033194472364688), id=19} 
2016-08-23 18:20:30.006 DEBUG 43846 --- [nio-8989-exec-9] org.hibernate.SQL      : insert into heartbeat (created_time, last_heartbeat_time, lifespan_sec, location, losted_sec, id) values (?, ?, ?, ?, ?, ?) 
Hibernate: insert into heartbeat (created_time, last_heartbeat_time, lifespan_sec, location, losted_sec, id) values (?, ?, ?, ?, ?, ?) 
2016-08-23 18:20:30.088 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.t.internal.jdbc.JdbcTransaction : committed JDBC Connection 
2016-08-23 18:20:30.088 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.t.internal.jdbc.JdbcTransaction : re-enabling autocommit 
2016-08-23 18:20:30.091 DEBUG 43846 --- [nio-8989-exec-9] m.m.a.RequestResponseBodyMethodProcessor : Written [[email protected]] as "application/json;charset=UTF-8" using [org.springfr[email protected]69f8302c] 
2016-08-23 18:20:30.091 DEBUG 43846 --- [nio-8989-exec-9] o.s.web.servlet.DispatcherServlet  : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling 
2016-08-23 18:20:30.091 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.jdbc.internal.JdbcCoordinatorImpl : HHH000420: Closing un-released batch 
2016-08-23 18:20:30.091 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.j.internal.LogicalConnectionImpl : Releasing JDBC connection 
2016-08-23 18:20:30.091 DEBUG 43846 --- [nio-8989-exec-9] o.h.e.j.internal.LogicalConnectionImpl : Released JDBC connection 

那麼,什麼是我的代碼,導致在beat1這種不同的結果的問題(的WebSocket)和beat2(HTTP請求)?

即使在調用MessageMapping方法beat1時,即使使用@Transactional註解,Spring似乎也不會自動給我一個事務,並且這種方法很奇怪。

+0

我實際上可以發現一個非常類似的問題在[這裏](http://stackoverflow.com/questions/25082234/jpa-存儲庫的WebSocket-messagemapping)。但是,該解決方案對我的情況沒有意義,因爲我正在使用'application.properties'文件來配置數據庫連接,JPA和Hibernate的自動配置 – junhanlin

回答

1

最後,我自己找到了解決方案。 事實證明,我有使用PlatformTransactionManager@Bean和使用JpaTransactionManager作爲實現手動configurate:

@ComponentScan 
    @Configuration 
    @EnableSwagger2 
    @EnableCaching 
    @EnableJpaRepositories 
    @EnableTransactionManagement 
    @EnableJpaAuditing 
    @SpringBootApplication 
    public class App 
    { 
     public static void main(String[] args) 
     { 
      SpringApplication.run(App.class, args); 
     } 

     @Autowired 
     private EntityManagerFactory entityManagerFactory; 

     @Bean 
     public PlatformTransactionManager transactionManager() 
     { 
     return new JpaTransactionManager(entityManagerFactory); 
     } 

    } 

這一切,那麼一切正常。

但我仍不明白爲什麼Spring Boot沒有使用我的applicaion.properites文件自動配置PlatformTransactionManager。 也許我誤解的東西或錯過的東西在application.properites,這裏是我的applicaion.properties看起來像:

# data source 
    spring.datasource.driver-class-name=org.postgresql.Driver 
    spring.datasource.url=jdbc:postgresql://xxx.xxx.xxx.xxxx:####/xxxx 
    spring.datasource.username=my-user-name 
    spring.datasource.password=my-password 
    spring.datasource.validationQuery=SELECT 1 
    spring.datasource.test-on-borrow=true 

    # jpa/hibernate 
    spring.jpa.hibernate.ddl-auto:validate 
    spring.jpa.show-sql:true 
    spring.jpa.properties.hibernate.dialect = org.hibernate.spatial.dialect.postgis.PostgisDialect 
    spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy 
    logging.level.org.hibernate=DEBUG 
相關問題