Hibernate问题与join fetch,”无法连接到基本类型的属性”。

huangapple go评论106阅读模式
英文:

Hibernate problems with join fetch "Cannot join to attribute of basic type"

问题

  1. 我在从SQLite数据库加载具有一对一关系的实体时遇到了问题
  2. 当我使用普通的CriteriaQuery来加载它们时一切正常但我在某个地方读到为了性能最好在查询中连接数据来源的两个表这样Hibernate就不会将其拆分为2个查询
  3. 当我尝试创建Fetch我遇到了`BasicPathUsageException: Cannot join to attribute of basic type`的错误
  4. 这是我用于创建查询的方法
  5. ```java
  6. private List<Task> loadTasks() {
  7. try {
  8. Session session = HibernateUtil.getSessionFactory().getCurrentSession();
  9. session.beginTransaction();
  10. CriteriaBuilder builder = session.getCriteriaBuilder();
  11. CriteriaQuery<Task> taskQuery = builder.createQuery(Task.class);
  12. Root<Task> taskTable = taskQuery.from(Task.class);
  13. Fetch<Task, TaskType> fetch = taskTable.fetch(TaskType_.ID, JoinType.LEFT); //<- 异常指向这里
  14. taskQuery.where(builder.equal(taskTable.get(TaskType_.ID).get("status"), "RECEIVED"));
  15. List<Task> loadedTasks= session.createQuery(taskQuery).getResultList();
  16. session.getTransaction().commit();
  17. return loadedTasks;
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. return null;
  21. }
  22. }

这是TaskType类:

  1. @Entity(name = "TaskType")
  2. @Table(name = "task_types")
  3. public class TaskType implements Serializable {
  4. private final SimpleIntegerProperty id = new SimpleIntegerProperty();
  5. private final SimpleStringProperty name = new SimpleStringProperty();
  6. @Id
  7. @Column(name = "task_type_id", unique = true)
  8. @GeneratedValue(strategy = GenerationType.IDENTITY)
  9. public int getId() {
  10. return id.get();
  11. }
  12. public void setId(int id) {
  13. this.id.set(id);
  14. }
  15. @Column(name = "task_type_name", unique = true)
  16. public String getName() {
  17. return name.get();
  18. }
  19. public void setName(String name) {
  20. this.name.set(name);
  21. }
  22. public SimpleIntegerProperty idProperty() {
  23. return id;
  24. }
  25. public SimpleStringProperty nameProperty() {
  26. return name;
  27. }

这是包含任务类型对象的Task类:

  1. @Entity(name = "Task")
  2. @Table(name = "tasks")
  3. public class Task implements Serializable {
  4. private final SimpleIntegerProperty id = new SimpleIntegerProperty();
  5. private final SimpleStringProperty name = new SimpleStringProperty();
  6. private TaskType type;
  7. @Id
  8. @Column(name = "task_id", unique = true)
  9. @GeneratedValue(strategy = GenerationType.IDENTITY)
  10. public int getId() {
  11. return id.get();
  12. }
  13. public void setId(int id) {
  14. this.id.set(id);
  15. }
  16. @Column(name = "task_name", unique = true)
  17. public String getName() {
  18. return name.get();
  19. }
  20. public void setName(String name) {
  21. this.name.set(name);
  22. }
  23. @OneToOne(fetch = FetchType.LAZY)
  24. @JoinColumn(name = "task_type_id")
  25. public TaskType getType() {
  26. return type;
  27. }
  28. public void setType(TaskType type) {
  29. this.type = type;
  30. }
  31. public SimpleStringProperty nameProperty() {
  32. return name;
  33. }
  34. public SimpleIntegerProperty idProperty() {
  35. return id;
  36. }

这个fetch()应该如何使用,或者如何使代码加载包括其任务类型的所有任务?我是不是在使用某个注解时出错了?

我试图查找异常的解决方法,但我找不到任何解决方案,也不知道如何将其应用到我的情况中。

感谢任何帮助!

  1. <details>
  2. <summary>英文:</summary>
  3. I&#39;m having problems with loading entities with a one-to-one relationship from a sqlite database.
  4. When I use a plain CriteriaQuery to load them everything works fine. But I&#39;ve read somwhere that for the performance it&#39;s better to join the two tables the data is coming from in the query so hibernate won&#39;t make 2 queries out of it.
  5. I am getting a `BasicPathUsageException: Cannot join to attribute of basic type` when I am trying to create a Fetch thingy.
  6. This is the method I use to create the query:
  1. private List&lt;Task&gt; loadTasks() {
  2. try {
  3. Session session = HibernateUtil.getSessionFactory().getCurrentSession();
  4. session.beginTransaction();
  5. CriteriaBuilder builder = session.getCriteriaBuilder();
  6. CriteriaQuery&lt;Task&gt; taskQuery = builder.createQuery(Task.class);
  7. Root&lt;Task&gt; taskTable = taskQuery.from(Task.class);
  8. Fetch&lt;Task, TaskType&gt; fetch = taskTable.fetch(TaskType_.ID, JoinType.LEFT); //&lt;- exception is pointing here
  9. taskQuery.where(builder.equal(taskTable.get(TaskType_.ID).get(&quot;status&quot;), &quot;RECEIVED&quot;));
  10. List&lt;Task&gt; loadedTasks= session.createQuery(taskQuery).getResultList();
  11. session.getTransaction().commit();
  12. return loadedTasks;
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. return null;
  16. }
  17. }
  1. This is the TaskType class:

@Entity(name = "TaskType")
@Table(name = "task_types")
public class TaskType implements Serializable {

  1. private final SimpleIntegerProperty id = new SimpleIntegerProperty();
  2. private final SimpleStringProperty name = new SimpleStringProperty();
  3. @Id
  4. @Column(name = &quot;task_type_id&quot;, unique = true)
  5. @GeneratedValue(strategy = GenerationType.IDENTITY)
  6. public int getId() {
  7. return id.get();
  8. }
  9. public void setId(int id) {
  10. this.id.set(id);
  11. }
  12. @Column(name = &quot;task_type_name&quot;, unique = true)
  13. public String getName() {
  14. return name.get();
  15. }
  16. public void setName(String name) {
  17. this.name.set(name);
  18. }
  19. public SimpleIntegerProperty idProperty() {
  20. return id;
  21. }
  22. public SimpleStringProperty nameProperty() {
  23. return name;
  24. }
  1. And this is the Task class which contains a task type object:

@Entity(name = "Task")
@Table(name = "tasks")
public class Task implements Serializable {

  1. private final SimpleIntegerProperty id = new SimpleIntegerProperty();
  2. private final SimpleStringProperty name = new SimpleStringProperty();
  3. private TaskType type;
  4. @Id
  5. @Column(name = &quot;task_id&quot;, unique = true)
  6. @GeneratedValue(strategy = GenerationType.IDENTITY)
  7. public int getId() {
  8. return id.get();
  9. }
  10. public void setId(int id) {
  11. this.id.set(id);
  12. }
  13. @Column(name = &quot;task_name&quot;, unique = true)
  14. public String getName() {
  15. return name.get();
  16. }
  17. public void setName(String name) {
  18. this.name.set(name);
  19. }
  20. @OneToOne(fetch = FetchType.LAZY)
  21. @JoinColumn(name = &quot;task_type_id&quot;)
  22. public TaskType getType() {
  23. return type;
  24. }
  25. public void setType(TaskType type) {
  26. this.type = type;
  27. }
  28. public SimpleStringProperty nameProperty() {
  29. return name;
  30. }
  31. public SimpleIntegerProperty idProperty() {
  32. return id;
  33. }
  1. How is this fetch() supposed to be used or how can I get the code to load all tasks including their task types? Am I using some annotation wrong?
  2. I tried to look the exception up but I could not find any solution or understand how to apply it to my situation.
  3. Thanks for any help!
  4. </details>
  5. # 答案1
  6. **得分**: 2
  7. `fetch`方法和`join`方法一样,仅适用于关联操作。
  8. 您可以使用以下方法替代:
  9. ```java
  10. taskTable.fetch(Task_.TYPE, JoinType.LEFT);
  11. taskQuery.where(builder.equal(taskTable.get(Task_.TYPE).get("status"), "RECEIVED"));
英文:

The fetch method, just like the join methods, only work on associations.

You use the following instead

  1. taskTable.fetch(Task_.TYPE, JoinType.LEFT);
  2. taskQuery.where(builder.equal(taskTable.get(Task_.TYPE).get(&quot;status&quot;), &quot;RECEIVED&quot;));

huangapple
  • 本文由 发表于 2020年8月16日 01:05:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/63428710.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定