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

Hibernate无法解决属性错误

师野
2023-03-14

我目前完全无法解决Hibernate的问题,我得到的消息是:

Your page request has caused a QueryException: could not resolve property: PERSON_ID of: library.model.Person [FROM library.model.Person p JOIN Book b ON p.PERSON_ID = b.PERSON_ID WHERE p.PERSON_ID = 2] error:

在以下方法中:

@Override
public Person getPersonAndBooks(Integer personId) {
    logger.info(PersonDAOImpl.class.getName() + ".listBooksForPerson() method called.");

    Session session = sessionFactory.openSession();                  
    Query query = session.createQuery("FROM Person p JOIN Book b ON p.PERSON_ID = b.PERSON_ID WHERE p.PERSON_ID = " + personId);                
    List<Person> persons = query.setResultTransformer(Transformers.aliasToBean(Person.class)).list();
    List<Book> books = persons.get(0).getBooks();
        for (Book b : books) {
           System.out.println("Here " + b.toString());
        }    
        return persons.get(0);  
    }        
    finally {
        session.close();
    }         
}

但是我在SQL中没有看到任何错误,它在阿帕奇德比中运行得很好。

我已经在 StackOverflow 和其他地方尝试了一些方法,但没有什么可以解决这个问题。

一个简单的应用程序中有两个类:

@Entity
@Table(name = "PERSON")
public class Person implements Serializable {

// Attributes.    
@Id
@Column(name="PERSON_ID", unique=true, nullable=false)    
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer personId;

@Column(name="NAME", nullable=false, length=50)      
private String name;

@Column(name="ADDRESS", nullable=false, length=100)
private String address;

@Column(name="TELEPHONE", nullable=false, length=10)
private String telephone;

@Column(name="EMAIL", nullable=false, length=50)
private String email;

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)     
private List<Book> books;

和书:

Entity
@Table(name = "BOOK")
public class Book implements Serializable {

// Attributes.
@Id
@Column(name="BOOK_ID", unique=true, nullable=false)
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer bookId;

@Column(name="AUTHOR", nullable=false, length=50)
private String author;

@Column(name="TITLE", nullable=false, length=50)
private String title;

@Column(name="DESCRIPTION", nullable=false, length=500)
private String description;

@Column(name="ONLOAN", nullable=false, length=5)
private String onLoan;

@ManyToOne
@JoinColumn(name="person_id")    
private Person person;

每个映射到数据库表:

CREATE TABLE PERSON (
  PERSON_ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),    
  NAME VARCHAR(50) NOT NULL,  
  ADDRESS VARCHAR(100) NOT NULL, 
  TELEPHONE VARCHAR(10) NOT NULL,
  EMAIL VARCHAR(50) NOT NULL,      
  CONSTRAINT PRIMARY_KEY_PERSON PRIMARY KEY(PERSON_ID)
)

而书是:

CREATE TABLE BOOK (
  BOOK_ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),    
  AUTHOR VARCHAR(50) NOT NULL,  
  TITLE VARCHAR(100) NOT NULL, 
  DESCRIPTION VARCHAR(500) NOT NULL,
  ONLOAN VARCHAR(5) NOT NULL,
  PERSON_ID INTEGER,   
  CONSTRAINT PRIMARY_KEY_BOOK PRIMARY KEY(ID),
  CONSTRAINT FOREIGN_KEY_BOOK FOREIGN KEY(PERSON_ID) REFERENCES PERSON(PERSON_ID)  
)

谁能告诉我哪里出了问题?

如果SQL最终起作用,如果我使用正确的方法将输出转换为Person对象,其中Person有Book的数组列表?

我给一个人买书的方法是:

// Calls books.jsp for a Person.
@RequestMapping(value = "/books", method = RequestMethod.GET)
public String listBooks(@RequestParam("personId") String personId, 
                        Model model) {    
    logger.info(PersonController.class.getName() + ".listBooks() method called."); 


    Person person = personService.get(Integer.parseInt(personId));  
    List<Book> books = bookService.listBooksForPerson(Integer.parseInt(personId));                

    // Set view.
    model.addAttribute("person", person);
    model.addAttribute("books", books);
    return "view/books";
}

这确实有效。

完整堆栈跟踪如下:

您的页面请求已导致LazyInitializationException:无法延迟初始化角色的集合:library.model.Person。books,无法初始化代理-无会话错误:

org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294)
library.controller.PersonController.getLogin(PersonController.java:104)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:483)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:744)

共有3个答案

楚钊
2023-03-14

如果我理解正确,在你从控制器返回(Person)session.get(Person.class,人ID)之后;这个人实例没有书,因为书是由惰性加载的。当你调用person.getBooks()时,它需要一个打开的会话来加载书,但是在你的DAO会话中已经关闭了最终块,这在内部导致LazyLaunalizationException:无法惰性初始化角色集合:library.model.Person.books,无法初始化代理-没有会话错误:

尝试快速加载书籍。

更改您的代码

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)     
private List<Book> books;
东方智敏
2023-03-14

使用标准API比HQL更安全:

@RequestMapping(value = "/books", method = RequestMethod.GET)
public String listBooks(@RequestParam("personId") String personId, 
                        Model model) {    

    Criteria query = session.createCriteria(Person.class);
    query.addRestriction("personId", personId);
    Person me = query.list().get(1);
    List<Book> myBooks = me.getBooks();
    model.setAttribute("person", me);
    model.setAttribute("books", myBooks);
    return "view/books";
}

更新

@Entity
@Table(name = "PERSON")
public class Person implements Serializable {

// Attributes.    
@Id
@Column(name="PERSON_ID", unique=true, nullable=false)    
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer personId;

@Column(name="NAME", nullable=false, length=50)      
private String name;

@Column(name="ADDRESS", nullable=false, length=100)
private String address;

@Column(name="TELEPHONE", nullable=false, length=10)
private String telephone;

@Column(name="EMAIL", nullable=false, length=50)
private String email;

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)     
private List<Book> books;
}
李云
2023-03-14

您编写 HQL 查询时,就好像它是 SQL 查询一样。HQL 和 JPQL 是不同的语言。

HQL从不使用表名和列名。它总是使用实体名称及其持久字段名(即personId而不是PERSON_ID)及其关联。HQL中的连接包括在实体间的关联中导航。因此,HQL查询没有on子句。

正确的 HQL 查询应为

 select p from Person p join p.books where p.id = :personId

请注意,我在查询中使用了一个必须绑定的命名参数,而不是使用连接,这是SQL注入攻击的大门(就像SQL一样)。

上述查询将选择由给定ID标识的人员,除非该人员没有任何书籍。您不需要任何结果转换器来获得这个查询的结果:它是一个Person实例。

我强烈建议您阅读Hibernate留档,它解释了HQL查询。

也就是说,您不需要任何查询来实现通过ID获取人员的方法。您需要的只是

Person p = (Person) session.get(Person.class, personId);
// now you can display the person and its books.
 类似资料:
  • 问题内容: 因此,我有一个表,已将其定义为hibernate状态,如下所示: 当我尝试针对此表编写一个简单查询时: 我收到以下错误: 为什么不能hibernate找出类上的dbgroupid? 问题答案: 可能是因为您的getter(和setter)没有遵循javabeans约定。它应该是: 我的建议是-命名字段,然后使用IDE生成设置器和获取器。它将遵循惯例。(另一件事,这是一个偏好问题,但我认

  • 现在我正在尝试从git运行克隆应用程序https://github.com/frinder/frinder-app但问题是该应用程序制作了很长时间,所以应该改变bulid.gradle 但是当我尝试相同的同步实现“com.android.支持:动画矢量可绘制:28.0.0”,但如果我删除它,请继续向我显示错误28.0.0它显示如下 但我不知道是什么造成了不完全相同的版本 这是应用程序build.g

  • 我正在尝试执行一个非常基本的查询,并收到org.hibernate.QueryException:无法解析属性。这是我的实体: @table(name="pm_screenconfiguration")公共类ScreenConfiguration扩展了PubleMovilEntity{ } 这是我的问题: 我真的搞不懂。Im使用MySql,所有列都具有相同的实体名称。 谢谢

  • 问题内容: 我刚刚下载了Hibernate 4.0.1最终版本的新版本。当我键入以下代码时,很奇怪: Eclipse IDE在STRING关键字上显示错误。我确定我的构建路径中有hibernatejar,并且还包含了以下代码: 我只是想知道为什么会发生这种情况? 问题答案: 因为该字段在4.0中不存在。 3.5中的现场文档说: 不推荐使用。 看到 http://opensource.atlassi

  • 下面是我的config.yml的一部分: 我有一个用于解析的类: 然而,当我跑的时候 发生以下错误: 为什么它抱怨找不到属性AuthenticationConfig而AuthenticationConfig只是实例变量的名称? 更新在我将实例变量从“private”更改为“public”后,它们被SnakeYaml识别,但这并不是我们所能肯定的。类不被识别为JavaBean。 更新我找到了根本原因

  • 问题内容: 我正在使用Hibernate 从表的列中获取值。 但是当我得到结果时,它会引发异常 org.hibernate.QueryException:无法解析属性:com.contaque.hibernateTableMappings.contaque_recording_log的文件名 我的食用豆是: 我从那里获取hibernate-session的hibernateUtil类: 我从表中获