交易从未完成Neo4j

时间:2014-06-30 08:56:40

标签: spring-mvc neo4j spring-data-neo4j spring-transactions

我有一个方法应该创建一个以这种方式定义的子图:

@Transactional
public Post createAndLink(Appuser appuser, Post post, String linkTo) {

    Post savedPost = null;
    if(post != null && appuser != null){
        post.setCreatedBy(appuser);
        if(post.getId() == null && post.getId() == ""){
            post.setId("IND"+GenerateUUID.getUUID());
        }
        System.out.println(">>> Id created : "+post.getId());

        //Date check
        String d = post.getDate();
        if(d != null && d.length() == 11 && ConversionUtils.isNumeric(d.substring(0, 4))
                && ConversionUtils.isNumeric(d.substring(5, 7)) && ConversionUtils.isNumeric(d.substring(8, 10))){
            if(!ConversionUtils.isPastDate(d)){
                System.out.println("Cannot save post with date after today");
                return null;
            }
        }

        System.out.println(">>> Date created : "+post.getDate());

        //People check
        Set<People> people = new HashSet<People>();
        if(post.getPeople() != null){
            for(People p : post.getPeople()){
                People pFromDb = peopleService.findById(p.getId());
                people.add(pFromDb != null ? pFromDb : new People("PPL"+GenerateUUID.getUUID(), p.getName()));
            }
            post.setPeople(people);
        }
        System.out.println(">>> People created : "+post.getPeople());

        //Place check
        if(post.getPlace() != null){
            Place pFromDb = placeService.findById(post.getPlace().getId());
            post.setPlace(pFromDb != null ? pFromDb : new Place(post.getPlace().getId()));
        }

        System.out.println(">>> Place created : "+post.getPlace());

        System.out.println("Post checking OK.");

        savedPost = repository.findById(linkTo);

        if(savedPost != null){
            Set<Post> linked = new HashSet<Post>();
            linked.add(savedPost);
            post.setLinkedPosts(linked);
        }
        template.save(post);

        System.out.println("=====> [saveWithUser]: Saved OK!");
    }

    return savedPost;
}

当我在循环中调用此方法时,有时会在执行template.save(post)时卡住(在其中一个迭代中)。

当我从GUI统一调用此方法时,会发现相同的行为。

PS:findBy方法不是事务性的。

自从2周以来我一直坚持下去,我无法找到解决方法:/

感谢您的反馈。

修改1:

方法生成的日志:

>>> Id created : IND6f770750-7834-40ae-a07e-fc81bbb3c657
>>> Date created : 2009Y09M20D
>>> People created : [People [id=PPLaf830449-b15c-4c71-b706-abd11492b825, name=Mary], People [id=PPLdf53d2c7-06b1-49c8-9b69-3b765d9b2ee6, name=Laptop]]
>>> Place created : Place [id=2918548, name=null]
Post checking OK.

PS:被阻止之前的迭代,它显示正常的日志执行但没有在DB中创建

编辑2

有时我会收到此错误(总是在第二次迭代期间,而1st显示正常日志但在DB上没有任何内容):

javax.transaction.RollbackException: Tx status is: STATUS_MARKED_ROLLBACK

1 个答案:

答案 0 :(得分:0)

我认为我发现了问题(但尚未解决)

我从服务方法中删除了所有@Transactional注释(控制器和存储库未标记为Transactional)。

在主帖中描述的createAndLink方法中,我以这种方式添加了事务:

if(post != null && appuser != null){
    Transaction tx = template.getGraphDatabaseService().beginTx();
    //I kept the same code...
    //...
    tx.success();
    tx.close();

}

现在,当我从控制器A调用此方法时,tx属于Placebo类型。当我从控制器B调用它时,tx类型是TopLevel。

我甚至通过从控制器B调用控制器A方法进行测试(如下例所示)并且它完美地工作(使用TopLevel Tx)。当我采取相反的方式时,Tx是安慰剂。

控制器A:

@RequestMapping(value="/newandlinksimilar/{linkedTo}", method=RequestMethod.POST)
public @ResponseBody boolean createAndLinkNewSimilar(@RequestBody Post post, @PathVariable String linkedTo){
        Post created = null;
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (post!= null && !(auth instanceof AnonymousAuthenticationToken)) {
            AppuserDetails userDetails = (AppuserDetails)auth.getPrincipal();
            Appuser currentUser = appuserService.findByLogin(userDetails.getUsername());
            created = postService.createAndLinkSimilar(currentUser, post, linkedTo);
        }
       return created;
}

控制器B:

@autowired
private ControllerA controllerA;

@RequestMapping("/init")
public ModelAndView init(){
    //I create a new Post object "post" with dummy data
    controllerA.createAndLinkSimilar(post,"XXXXXX");
    //Or postService.createAndLinkSimilar(appuser,post,"XXXXXX");
    return new ModelAndView("home");
}

两个测试都是通过GUI ajax调用控制器方法完成的。

我无法理解Spring何时以及如何选择交易类型?!