我正在努力通过使用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?
很抱歉这篇长篇文章并提前感谢你。