Java Spring PagingAndSortingRepository异常

时间:2016-09-20 14:24:00

标签: java spring hibernate pagination

我正在努力通过使用PagingAndSortingRepository在我的Spring网络应用程序中找到jpa-s列表,但我总是遇到某种异常。 (我的userRepository扩展了扩展PagingAndSortingRepository的JpaRepository)

这是我的代码:

@RestController
@RequestMapping(value = "")
public class UsersController {
    ...
    @RequestMapping(method=RequestMethod.GET, value = "/view-u", produces = MediaType.APPLICATION_JSON_VALUE)
    @PreAuthorize("hasRole(T(com.myapp.util.Um.Privileges).CAN_USER_READ)")
    public @ResponseBody List<JsonUser> getUsersPaginated(){
        List<JsonUser> result = new ArrayList<JsonUser>();

        result.addAll(dashboardServiceImpl.findUsersPaginatedAndSorted());

        return result;
    }
    ...
}

和服务:

@Service
public class DasboardServiceImpl implements DashboardService /*My interface*/{

    ...
    @Override
    public List<JsonUser> findUsersPaginatedAndSorted(){
        List<JsonUser> modelList = new ArrayList<JsonUser>();

        final List<UserJPA> jpaList = userRepository.findAll(new PageRequest(0, 10, Sort.Direction.ASC, "username")).getContent();

        for(final UserJPA jpa : jpaList){
            modelList.add(new JsonUser(jpa));
        }

        return modelList;
    }
}

这不起作用。它引发了异常:

  

枚举类的未知名称值[] [com.health.common.enums.Gender];   嵌套异常是java.lang.IllegalArgumentException:未知名称   enum类的值[] [com.health.common.enums.Gender]

我证明了Gender enum在所有其他数据库通信中都能很好地工作。

然后我尝试对服务方法执行此操作:

    @Override
    public List<JsonUser> findUsersPaginatedAndSorted(){
        List<JsonUser> modelList = new ArrayList<JsonUser>();

        try{
            // First call -> enum exception
            userRepository.findAll(new PageRequest(0, 10, Sort.Direction.ASC, "username"));
        }catch(Exception e){
            System.out.println("\n\t"+e.getMessage()+"\n");
        }

        // Second call - collection exception
        final List<UserJPA> jpaList = userRepository.findAll(new PageRequest(0, 10, Sort.Direction.ASC, "username")).getContent();

        for(final UserJPA jpa : jpaList){
            modelList.add(new JsonUser(jpa));
        }

        return modelList;
    }

这一次,我在第二个findAll调用中得到了一个不同的例外:

  

org.springframework.orm.jpa.JpaSystemException:集合不是   与任何会话相关联;嵌套异常是   org.hibernate.HibernateException:collection与之无关   任何会议

经过大量的挖掘和挫折之后,我找到了唯一适合我的解决方案: 我将@Transactional(readOnly = true)添加到服务方法并捕获服务和控制器中的不同异常:

控制器:

@RestController
@RequestMapping(value = "")
public class UsersController {
    ...
    @RequestMapping(method=RequestMethod.GET, value = "/view-u", produces = MediaType.APPLICATION_JSON_VALUE)
    @PreAuthorize("hasRole(T(com.health.common.util.Um.Privileges).CAN_USER_READ)")
    public @ResponseBody List<JsonUser> getUsersPaginated(){
        List<JsonUser> result = new ArrayList<JsonUser>();
        // i have no idea why
        try{
            // when called the first time, it throws "Transaction marked as rollbackOnly"
            result.addAll(dashboardServiceImpl.findUsersPaginatedAndSorted());
        }catch(Exception e){
            // and when called the second time, it works
            result.addAll(dashboardServiceImpl.findUsersPaginatedAndSorted());
        }

        return result;
    }
    ...
}

(请注意我在第一次服务方法调用时遇到的异常是:

  

TransactionSystemException:无法提交JPA事务;嵌套   异常是javax.persistence.RollbackException:标记了事务   作为rollbackOnly   )

服务:

@Service
public class DasboardServiceImpl implements DashboardService{

    ...
    @Override
    @Transactional(readOnly=true)
    public List<JsonUser> findUsersPaginatedAndSorted(){
        List<JsonUser> modelList = new ArrayList<JsonUser>();

        // I have no idea why
        try{
            // when called the first time it throws (GenderEnum) exception
            userRepository.findAll(new PageRequest(0, 10, Sort.Direction.ASC, "username"));
        }catch(Exception e){
            System.out.println("\n\t"+e.getMessage()+"\n");
        }

        // and when called the second time, it works
        final List<UserJPA> jpaList = userRepository.findAll(new PageRequest(0, 10, Sort.Direction.ASC, "username")).getContent();

        for(final UserJPA jpa : jpaList){
            modelList.add(new JsonUser(jpa));
        }

        return modelList;
    }
}

正如我所说,这对我有用,我得到了一个合适的用户列表,但这个解决方案远非优雅。请注意,我正在对服务方法和存储库方法进行双重调用。 :(

如何修复我的代码,以便我不必进行这些双重调用?

为什么我的原始解决方案不起作用?为什么findAll(Paginated)在不改变数据库的查询时需要@Transactional?

很抱歉这篇长篇文章并提前感谢你。

0 个答案:

没有答案