当前位置: 首页 > 知识库问答 >
问题:

JpaRepository JOIN JPQL查询与可分页对象。如何实现?

章琛
2023-03-14

我有两个表user和userprofiles。

使用者

mysql> SHOW columns FROM user;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| name     | varchar(45)  | YES  |     | NULL    |                |
| password | varchar(255) | NO   |     | NULL    |                |
| email    | varchar(45)  | NO   | UNI | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)

和用户配置文件

mysql> SHOW columns FROM userprofiles;
+---------------+---------------+------+-----+-------------------------+----------------+
| Field         | Type          | Null | Key | Default                 | Extra          |
+---------------+---------------+------+-----+-------------------------+----------------+
| userprofileid | int(11)       | NO   | PRI | NULL                    | auto_increment |
| userid        | int(11)       | NO   | MUL | NULL                    |                |
| userpics      | varchar(45)   | YES  |     | /images/faces/face2.jpg |                |.
.
.
.
| datecreated   | datetime      | YES  |     | CURRENT_TIMESTAMP       |                |
+---------------+---------------+------+-----+-------------------------+----------------+
15 rows in set (0.00 sec)

这两个实体是一对一的关系。

@Entity
@Table(name="user")
public class User {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;
...
..
    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
    private UserProfile userProfile;
..

和用户描述实体

@Entity
@Table(name="userprofiles")
public class UserProfile {

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    @JoinColumn(name="userid")
    private User user;

    @Id
    private int id;
...
..

正如您所看到的,只有在UserProlie表中有一个datecreated信息。我想做的是,按datecreated获取所有User降序。

所以,在我的控制器里。

@GetMapping("/allUserInfo")
    public String getAllUserInfo(@PageableDefault(page = 1) Pageable pageable, Model model) { 

        int pageNum = pageable.getPageNumber(); 
        pageable = new PageRequest(pageNum, 10, new Sort(Sort.Direction.DESC, "datecreated"));

        Page<User> users = userService.findAll(pageable);
        model.addAttribute("users", users);

        return "_allUserInfo";
    }

因为我的DAO接口扩展了JpaRepository类。我试过这样。。

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserDAO userDAO;
..
.
    @Override
    public Page<User> findAll(Pageable pageable) {
        return userDAO.findAll(pageable);
    }
..
@Repository
public interface UserDAO extends JpaRepository<User, Long> {

    @Query("SELECT u FROM userprofile upf JOIN upf.user u")
    Page<User> findAll(Pageable pageable);
}

但它失败了。。我只想获取按datecreated排序的用户可分页对象。以便我可以向视图显示它。我走对了吗?还是有其他方法?

Validation failed for query for method public abstract org.springframework.data.domain.Page com.myfolder.boards.dao.UserDAO.findAll(org.springframework.data.domain.Pageable)!

Above is error msg..

编辑-完整错误消息

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl': Unsatisfied dependency expressed through field 'userDAO'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDAO': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract org.springframework.data.domain.Page com.rainbowtape.boards.dao.UserDAO.findAll(org.springframework.data.domain.Pageable)!
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:592)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:370)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:754)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4641)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5109)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1427)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1417)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:943)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:839)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1427)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1417)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:943)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:258)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:770)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:682)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl': Unsatisfied dependency expressed through field 'userDAO'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDAO': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract org.springframework.data.domain.Page com.rainbowtape.boards.dao.UserDAO.findAll(org.springframework.data.domain.Pageable)!
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:592)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:370)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1131)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:589)
    ... 45 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDAO': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract org.springframework.data.domain.Page com.rainbowtape.boards.dao.UserDAO.findAll(org.springframework.data.domain.Pageable)!
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1131)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:589)
    ... 58 more
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract org.springframework.data.domain.Page com.rainbowtape.boards.dao.UserDAO.findAll(org.springframework.data.domain.Pageable)!
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:92)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:62)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:72)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:53)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:138)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:205)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:77)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:451)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:223)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:101)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
    ... 68 more
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: userprofile is not mapped [SELECT u FROM userprofile upf JOIN upf.user u]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:138)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:713)
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347)
    at com.sun.proxy.$Proxy74.createQuery(Unknown Source)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:86)
    ... 81 more
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: userprofile is not mapped [SELECT u FROM userprofile upf JOIN upf.user u]
    at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:79)
    at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:219)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:143)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:119)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
    at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:595)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:704)
    ... 89 more
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: userprofile is not mapped
    at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:169)
    at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:91)
    at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:79)
    at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:331)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3695)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3584)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:720)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:576)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:271)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:191)
    ... 95 more

编辑2

我真傻。

@Query("SELECT u FROM UserProfile upf JOIN upf.user u")

这起作用了。

共有3个答案

邹时铭
2023-03-14

这有点老了,但我会放在这里,以便将来参考。

您可以使用JPQL(允许分页)或本机查询(需要更多工作):

  1. JPQL(在这种情况下,分页非常容易):
@Query(value = "SELECT u FROM User u ORDER BY id")
Page<User> findAllUsersWithPagination(Pageable pageable);
@Query(
  value = "SELECT * FROM Users ORDER BY id", 
  countQuery = "SELECT count(*) FROM Users", 
  nativeQuery = true)
Page<User> findAllUsersWithPagination(Pageable pageable);

我从Baeldung那里得到了这个密码。

鲁钱明
2023-03-14

你的问题有很多问题:

1-您正在查询查询中的整个实体“用户u”。是否确实需要所有属性?也许您应该对一个DTO使用带构造函数的查询。(这里的manish答案中的示例)如何通过查询从Spring数据JPA GROUP返回自定义对象

2-您正在用户中查询并按不在用户实体中的字段排序。也许您应该在UserProfile存储库中使用此查询。或者,您可以在排序字段中添加“userProfile.datecreated”,而不是“datecreated”,看看这是否解决了您的问题。

3-不要隐藏错误消息。如果我看到了,我可能会帮你更多。

萧英光
2023-03-14

请看一下:https://www.baeldung.com/spring-data-jpa-pagination-sorting

您可以扩展分页和排序存储库界面:

public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {

    List<Product> findAllByPrice(double price, Pageable pageable);
}

然后您可以执行以下操作:

Pageable sortedByName = 
  PageRequest.of(0, 3, Sort.by("name"));

Pageable sortedByPriceDesc = 
  PageRequest.of(0, 3, Sort.by("price").descending());

Pageable sortedByPriceDescNameAsc = 
  PageRequest.of(0, 5, Sort.by("price").descending().and(Sort.by("name")));
 类似资料:
  • 本文向大家介绍如何用java实现分页查询,包括了如何用java实现分页查询的使用技巧和注意事项,需要的朋友参考一下 1.基本思路 我现阶段的分页查询的实现是基于sql语句的。 构造出相应的a和b就可以查询出想要的数据,在显示在页面上。重点是要构造出当前的页数,就要封装一个javaBean,存储有关分页的基本属性。 这样只需在service层计算想要的页数,并封装基本的信息,在查询出来显示在前端就可

  • 本文向大家介绍ajax实现分页和分页查询,包括了ajax实现分页和分页查询的使用技巧和注意事项,需要的朋友参考一下 之前有写过ajax的加载页面,是非常简单的,而且不需要重新刷新页面,写起来也是非常的方便,今天写的分页是不用封装page.class.php的,是单纯的js和ajax写出来的 首先为了页面的整齐与美观,我用到了bootstrap,需要引进所需要的文件包 下面是页面显示的内容 下面是j

  • 本文向大家介绍请说明一下Hibernate如何实现分页查询?相关面试题,主要包含被问及请说明一下Hibernate如何实现分页查询?时的应答技巧和注意事项,需要的朋友参考一下 考察点:框架 参考回答: 通过Hibernate实现分页查询,开发人员只需要提供HQL语句(调用Session的createQuery()方法)或查询条件(调用Session的createCriteria()方法)、设置查询

  • 使用数据库的应用程序,多数情况下都需要使用 “分页” 这个功能。尤其是在 Web 应用程序中,后端的分页查询尤其的普遍。 在以往的使用经验中,一个分页查询,除了能获取到一个列表外,我们通常需要如下几个信息才能在客户端显示出一个完整的翻页条。 当前页数 -- 第几页 页大小 -- 每页有多少条记录 总页数 -- 一共多少页 总记录数 -- 如果不分页,一共有多少条记录 当我们获得了这四条信息后,对于

  • limt 分页查询 查询前3条记录 分页公式: (offset - 1) * limit SELECT name FROM `student` LIMIT 0, 3; Student.findAll( { attributes:['name'], // 当前页 offset:0, // 每页显示的条数 limit:3 }) 分页案例 router.ge

  • 在使用 hyperf/database 来查询数据时,可以很方便的通过与 hyperf/paginator 组件配合便捷地对查询结果进行分页。 使用方法 在您通过 查询构造器 或 模型 查询数据时,可以通过 paginate 方法来处理分页,该方法会自动根据用户正在查看的页面来设置限制和偏移量,默认情况下,通过当前 HTTP 请求所带的 page 参数的值来检测当前的页数: 由于 Hyperf 当