【问题标题】:Why is Hibernate looking in the wrong place为什么 Hibernate 找错地方了
【发布时间】:2022-01-07 05:58:47
【问题描述】:

您好,我是 Java 和 Spring 本身的新手。现在我在学习JPA,一般来说,问题是这样的:当我的驱动中有这个列时,为什么Hibernate会在BaseEntity中查找last_name列?

当我尝试调用 findAll 并使用 dateTable 的概念创建查询时,这一切都会发生

Git Hub 中的项目:https://github.com/Slizzardd/nix_10/tree/master/hw_9_web_jpa

错误:

java.lang.IllegalArgumentException: Unable to locate Attribute  with the the given name [last_name] on this ManagedType [ua.com.alevel.persistence.entity.BaseEntity]
    at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.checkNotNull(AbstractManagedType.java:148)
    at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:119)
    at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:117)
    at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:44)
    at org.hibernate.query.criteria.internal.path.AbstractFromImpl.locateAttributeInternal(AbstractFromImpl.java:111)
    at org.hibernate.query.criteria.internal.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:204)
    at org.hibernate.query.criteria.internal.path.AbstractPathImpl.get(AbstractPathImpl.java:177)
    at ua.com.alevel.persistence.dao.impl.DriverDaoImpl.findAll(DriverDaoImpl.java:90)
    at ua.com.alevel.persistence.dao.impl.DriverDaoImpl$$FastClassBySpringCGLIB$$70e9ea23.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at ua.com.alevel.persistence.dao.impl.DriverDaoImpl$$EnhancerBySpringCGLIB$$3de59a25.findAll(<generated>)
    at ua.com.alevel.service.impl.DriverServiceImpl.findAll(DriverServiceImpl.java:60)
    at ua.com.alevel.facade.impl.DriverFacadeImpl.findAll(DriverFacadeImpl.java:64)
    at ua.com.alevel.view.controller.DriverController.findAll(DriverController.java:41)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:833)

我的 BaseEntity:

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @Temporal(TemporalType.TIMESTAMP)
    private Date updated;


    private Boolean visible;

    @Column(name = "image_url")
    private String imageUrl;

    public BaseEntity() {
        this.created = new Date();
        this.updated = new Date();
        this.visible = true;
    }

    @PreUpdate
    public void preUpdate() {
        this.updated = new Date();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getUpdated() {
        return updated;
    }

    public void setUpdated(Date updated) {
        this.updated = updated;
    }

    public Boolean getVisible() {
        return visible;
    }

    public void setVisible(Boolean visible) {
        this.visible = visible;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }
}

我的司机:

@Entity
@Table(name = "drivers")
public class Driver extends BaseEntity {

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    private String notes;
    private double balance;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "driver_car",
            joinColumns = @JoinColumn(name = "driver_id"),
            inverseJoinColumns = @JoinColumn(name = "car_id"))
    private Set<Car> cars;

    public Driver() {
        super();
        this.cars = new HashSet<>();
    }

    public Set<Car> getCars() {
        return cars;
    }

    public void setCars(Set<Car> cars) {
        this.cars = cars;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getNotes() {
        return notes;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

DriverDaoImpl 中的methodFindAll:

    @Override
        public DataTableResponse<Driver> findAll(DataTableRequest request) throws Exception {
            List<Driver> drivers;
            Map<Object, Object> otherParamMap = new HashMap<>();
            CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
            CriteriaQuery<Driver> criteriaQuery = criteriaBuilder.createQuery(Driver.class);
            Root<Driver> from = criteriaQuery.from(Driver.class);
            int page = (request.getCurrentPage() - 1) * request.getPageSize();
            int size = page + request.getPageSize();
    
            if(request.getSort().equals("carCount")){
                Query query;
                if (request.getOrder().equals("desc")) {
                    query = entityManager.createQuery("select d from Driver d where d.visible = true order by d.cars.size desc")
                            .setFirstResult(page)
                            .setMaxResults(size);
                } else {
                    query = entityManager.createQuery("select d from Driver d where d.visible = true order by d.cars.size asc")
                            .setFirstResult(page)
                            .setMaxResults(size);
                }
                drivers = query.getResultList();
            }else {
                try{
                    if (request.getOrder().equals("desc")) {
                        criteriaQuery.orderBy(criteriaBuilder.desc(from.get(request.getSort())));
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.asc(from.get(request.getSort())));
                    }
                }catch (Exception e){
                    e.printStackTrace();;
                }
    
                drivers = entityManager.createQuery(criteriaQuery)
                        .setFirstResult(page)
                        .setMaxResults(size)
                        .getResultList();
            }
    
            for (int i = 0; i < drivers.size(); i++) {
                otherParamMap.put(drivers.get(i).getId(), countNumOfCars(drivers.get(i).getId()));
            }
            DataTableResponse<Driver> response = new DataTableResponse<>();
    
            response.setSort(request.getSort());
            response.setOrder(request.getOrder());
            response.setCurrentPage(request.getCurrentPage());
            response.setCurrentSize(request.getPageSize());
            response.setItems(drivers);
            response.setOtherParamMap(otherParamMap);
    
            return response;
        }
    
        private int countNumOfCars(Long id) {
            return findById(id).getCars().size();
        }

我的休眠配置:

@Configuration
@EnableTransactionManagement
public class HibernateConfig {

    @Value("${spring.datasource.url}")
    private String jdbcUrl;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driver-class-name}")
    private String driver;

    @Value("${spring.jpa.properties.hibernate.dialect}")
    private String dialect;

    @Value("${spring.jpa.hibernate.ddl-auto}")
    private String hbm2ddl;

    @Value("${spring.jpa.show-sql}")
    private Boolean showSql;

    @Value("${spring.jpa.properties.hibernate.jdbc.max_size}")
    private String maxSize;

    @Value("${spring.jpa.properties.hibernate.jdbc.min_size}")
    private String minSize;

    @Value("${spring.jpa.properties.hibernate.jdbc.batch_size}")
    private String batchSize;

    @Value("${spring.jpa.properties.hibernate.jdbc.fetch_size}")
    private String fetchSize;

    @Value("${spring.jpa.properties.hibernate.enable_lazy_load_no_trans}")
    private String lazyLoad;

    private static final String HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
    private static final String HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String HIBERNATE_ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
    private static final String MAX_SIZE = "hibernate.c3p0.max_size";
    private static final String MIN_SIZE = "hibernate.c3p0.min_size";
    private static final String BATCH_SIZE = "hibernate.jdbc.batch_size";
    private static final String FETCH_SIZE = "hibernate.jdbc.fetch_size";
    private static final String ENTITY_MANAGER_PACKAGES_TO_SCAN = "ua.com.alevel.persistence.entity";

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager manager = new HibernateTransactionManager();
        manager.setSessionFactory(sessionFactoryBean().getObject());
        return manager;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactoryBean() {
        LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource());
        sessionFactoryBean.setPackagesToScan(ENTITY_MANAGER_PACKAGES_TO_SCAN);
        sessionFactoryBean.setHibernateProperties(hibernateProperties());
        try {
            sessionFactoryBean.afterPropertiesSet();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sessionFactoryBean;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put(HIBERNATE_DIALECT, dialect);
        properties.put(HIBERNATE_HBM2DDL_AUTO, hbm2ddl);
        properties.put(HIBERNATE_SHOW_SQL, showSql);
        properties.put(HIBERNATE_ENABLE_LAZY_LOAD_NO_TRANS, lazyLoad);
        properties.put(MAX_SIZE, maxSize);
        properties.put(MIN_SIZE, minSize);
        properties.put(BATCH_SIZE, batchSize);
        properties.put(FETCH_SIZE, fetchSize);
        return properties;
    }
}

我的 application.properties:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/taxi_bd?useSSL=false&serverTimezone=UTC&createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.platform=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.jdbc.fetch_size=50
spring.jpa.properties.hibernate.jdbc.max_size=25
spring.jpa.properties.hibernate.jdbc.min_size=10
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

我的主应用程序:

@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class })
public class WebJpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebJpaApplication.class, args);
    }
}

【问题讨论】:

    标签: java spring hibernate jpa


    【解决方案1】:

    问题出在这里:

    criteriaQuery.orderBy(criteriaBuilder.desc(from.get(request.getSort())));
    // and here
    criteriaQuery.orderBy(criteriaBuilder.asc(from.get(request.getSort())));
    

    更具体地说这部分:

    from.get(request.getSort())
    

    因为在请求中您将列名称发送为last_name,而不是属性名称lastName。您必须在 JPQL 和 Criteria Queries(被翻译成 JPQL)中使用 java 属性名,而不是本地数据库列名。

    【讨论】:

      【解决方案2】:

      解决方案可能不太好,但我决定只在函数中添加一个 if else,这是之前的函数:

      @Override
              public DataTableResponse<Driver> findAll(DataTableRequest request) throws Exception {
                  List<Driver> drivers;
                  Map<Object, Object> otherParamMap = new HashMap<>();
                  CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
                  CriteriaQuery<Driver> criteriaQuery = criteriaBuilder.createQuery(Driver.class);
                  Root<Driver> from = criteriaQuery.from(Driver.class);
                  int page = (request.getCurrentPage() - 1) * request.getPageSize();
                  int size = page + request.getPageSize();
          
                  if(request.getSort().equals("carCount")){
                      Query query;
                      if (request.getOrder().equals("desc")) {
                          query = entityManager.createQuery("select d from Driver d where d.visible = true order by d.cars.size desc")
                                  .setFirstResult(page)
                                  .setMaxResults(size);
                      } else {
                          query = entityManager.createQuery("select d from Driver d where d.visible = true order by d.cars.size asc")
                                  .setFirstResult(page)
                                  .setMaxResults(size);
                      }
                      drivers = query.getResultList();
                  }else {
                      try{
                          if (request.getOrder().equals("desc")) {
                              criteriaQuery.orderBy(criteriaBuilder.desc(from.get(request.getSort())));
                          } else {
                              criteriaQuery.orderBy(criteriaBuilder.asc(from.get(request.getSort())));
                          }
                      }catch (Exception e){
                          e.printStackTrace();;
                      }
          
                      drivers = entityManager.createQuery(criteriaQuery)
                              .setFirstResult(page)
                              .setMaxResults(size)
                              .getResultList();
                  }
          
                  for (int i = 0; i < drivers.size(); i++) {
                      otherParamMap.put(drivers.get(i).getId(), countNumOfCars(drivers.get(i).getId()));
                  }
                  DataTableResponse<Driver> response = new DataTableResponse<>();
          
                  response.setSort(request.getSort());
                  response.setOrder(request.getOrder());
                  response.setCurrentPage(request.getCurrentPage());
                  response.setCurrentSize(request.getPageSize());
                  response.setItems(drivers);
                  response.setOtherParamMap(otherParamMap);
          
                  return response;
              }
          
              private int countNumOfCars(Long id) {
                  return findById(id).getCars().size();
              }
      

      之后:

      @Override
          public DataTableResponse<Driver> findAll(DataTableRequest request) throws Exception {
              List<Driver> drivers;
              Map<Object, Object> otherParamMap = new HashMap<>();
              CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
              CriteriaQuery<Driver> criteriaQuery = criteriaBuilder.createQuery(Driver.class);
              Root<Driver> from = criteriaQuery.from(Driver.class);
              int page = (request.getCurrentPage() - 1) * request.getPageSize();
              int size = page + request.getPageSize();
      
              if (request.getSort().equals("carCount")) {
                  Query query;
                  if (request.getOrder().equals("desc")) {
                      query = entityManager.createQuery("select d from Driver d where d.visible = true order by d.cars.size desc")
                              .setFirstResult(page)
                              .setMaxResults(size);
                  } else {
                      query = entityManager.createQuery("select d from Driver d where d.visible = true order by d.cars.size asc")
                              .setFirstResult(page)
                              .setMaxResults(size);
                  }
                  drivers = query.getResultList();
              } else if (request.getSort().equals("first_name") || request.getSort().equals("last_name")) {
                  Query query;
                  if (request.getOrder().equals("desc")) {
                      query = entityManager.createQuery("select d from Driver d where d.visible = true order by " + request.getSort() + " desc")
                              .setFirstResult(page)
                              .setMaxResults(size);
                  } else {
                      query = entityManager.createQuery("select d from Driver d where d.visible = true order by " + request.getSort() + " asc")
                              .setFirstResult(page)
                              .setMaxResults(size);
                  }
                  drivers = query.getResultList();
              } else {
                  try {
                      if (request.getOrder().equals("desc")) {
                          criteriaQuery.orderBy(criteriaBuilder.desc(from.get(request.getSort())));
                      } else {
                          criteriaQuery.orderBy(criteriaBuilder.asc(from.get(request.getSort())));
                      }
                  } catch (Exception e) {
                      e.printStackTrace();
                      ;
                  }
      
                  drivers = entityManager.createQuery(criteriaQuery)
                          .setFirstResult(page)
                          .setMaxResults(size)
                          .getResultList();
              }
      
              for (int i = 0; i < drivers.size(); i++) {
                  otherParamMap.put(drivers.get(i).getId(), countNumOfCars(drivers.get(i).getId()));
              }
              DataTableResponse<Driver> response = new DataTableResponse<>();
      
              response.setSort(request.getSort());
              response.setOrder(request.getOrder());
              response.setCurrentPage(request.getCurrentPage());
              response.setCurrentSize(request.getPageSize());
              response.setItems(drivers);
              response.setOtherParamMap(otherParamMap);
      
              return response;
          }
      
          private int countNumOfCars(Long id) {
              return findById(id).getCars().size();
          }
      

      【讨论】:

        猜你喜欢
        • 2017-12-18
        • 1970-01-01
        • 2022-11-23
        • 2015-10-15
        • 1970-01-01
        • 1970-01-01
        • 2012-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多