Transactions SpringDataNeo4j如何选择事务类型(安慰剂或顶级)

Transactions SpringDataNeo4j如何选择事务类型(安慰剂或顶级),transactions,neo4j,spring-data-neo4j,Transactions,Neo4j,Spring Data Neo4j,我有一个方法可以创建一个子图,它是这样定义的: public Post createAndLink(Appuser appuser, Post post, String linkTo) { Transaction tx = template.getGraphDatabaseService().beginTx(); Post savedPost = null; if(post != null && appuser != null){ pos

我有一个方法可以创建一个子图,它是这样定义的:

public Post createAndLink(Appuser appuser, Post post, String linkTo) {
    Transaction tx = template.getGraphDatabaseService().beginTx();
    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!");
        tx.success();
        tx.close();
    }

    return savedPost;
}
控制器B:

@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;
}
@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何时以及如何选择事务类型

安慰剂事务是Neo4j中的嵌套事务,它们是在已经有顶级事务运行时创建的,并且仅在以下情况下影响顶级事务:

  • 未完成
  • 后退
  • 终止
因此,不知何故(可能是视图中的某些开放事务自动)已经在您的应用程序中围绕第一个控制器(a)或您以前调用的东西创建了一个顶级tx,就像您的服务没有正确完成它的事务一样,所以它们仍然在运行

也许你可以提前返回某个地方而不打电话给close

我还建议使用try-with-resource模式,它在块的末尾自动关闭事务,否则在
finally
中执行
close

try (Transaction tx = db.beginTx()) {
   ... your database code ...
   tx.success()
}

真奇怪!!如您所见,我在控制器中没有事务。我试图在控制器的开头添加一个新事务。它的类型也是安慰剂。此控制器是入口点,因此它应该是应该执行的控制器:/而且我已经重新启动了Web服务器。可能是因为数据库中某个地方的文件丢失了吗?
appuserService.findByLogin
do做什么?@覆盖公共Appuser findByLogin(字符串登录){return repository.findByLogin(login);}和存储库方法:@Query(“MATCH(u:Appuser)WHERE u.login={0}return u”)公共Appuser findByLogin(字符串登录);也许你可以公开一个小的单元测试来公开这个行为,我以前也看过,所以不能复制。非常感谢你的帮助。我发现我没有用另一种方法(获取其他数据)正确关闭事务。