英文:
Hibernate problems with join fetch "Cannot join to attribute of basic type"
问题
我在从SQLite数据库加载具有一对一关系的实体时遇到了问题。
当我使用普通的CriteriaQuery来加载它们时,一切正常。但我在某个地方读到,为了性能,最好在查询中连接数据来源的两个表,这样Hibernate就不会将其拆分为2个查询。
当我尝试创建Fetch时,我遇到了`BasicPathUsageException: Cannot join to attribute of basic type`的错误。
这是我用于创建查询的方法:
```java
private List<Task> loadTasks() {
try {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Task> taskQuery = builder.createQuery(Task.class);
Root<Task> taskTable = taskQuery.from(Task.class);
Fetch<Task, TaskType> fetch = taskTable.fetch(TaskType_.ID, JoinType.LEFT); //<- 异常指向这里
taskQuery.where(builder.equal(taskTable.get(TaskType_.ID).get("status"), "RECEIVED"));
List<Task> loadedTasks= session.createQuery(taskQuery).getResultList();
session.getTransaction().commit();
return loadedTasks;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
这是TaskType类:
@Entity(name = "TaskType")
@Table(name = "task_types")
public class TaskType implements Serializable {
private final SimpleIntegerProperty id = new SimpleIntegerProperty();
private final SimpleStringProperty name = new SimpleStringProperty();
@Id
@Column(name = "task_type_id", unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
@Column(name = "task_type_name", unique = true)
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public SimpleIntegerProperty idProperty() {
return id;
}
public SimpleStringProperty nameProperty() {
return name;
}
这是包含任务类型对象的Task类:
@Entity(name = "Task")
@Table(name = "tasks")
public class Task implements Serializable {
private final SimpleIntegerProperty id = new SimpleIntegerProperty();
private final SimpleStringProperty name = new SimpleStringProperty();
private TaskType type;
@Id
@Column(name = "task_id", unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
@Column(name = "task_name", unique = true)
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "task_type_id")
public TaskType getType() {
return type;
}
public void setType(TaskType type) {
this.type = type;
}
public SimpleStringProperty nameProperty() {
return name;
}
public SimpleIntegerProperty idProperty() {
return id;
}
这个fetch()应该如何使用,或者如何使代码加载包括其任务类型的所有任务?我是不是在使用某个注解时出错了?
我试图查找异常的解决方法,但我找不到任何解决方案,也不知道如何将其应用到我的情况中。
感谢任何帮助!
<details>
<summary>英文:</summary>
I'm having problems with loading entities with a one-to-one relationship from a sqlite database.
When I use a plain CriteriaQuery to load them everything works fine. But I've read somwhere that for the performance it's better to join the two tables the data is coming from in the query so hibernate won't make 2 queries out of it.
I am getting a `BasicPathUsageException: Cannot join to attribute of basic type` when I am trying to create a Fetch thingy.
This is the method I use to create the query:
private List<Task> loadTasks() {
try {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Task> taskQuery = builder.createQuery(Task.class);
Root<Task> taskTable = taskQuery.from(Task.class);
Fetch<Task, TaskType> fetch = taskTable.fetch(TaskType_.ID, JoinType.LEFT); //<- exception is pointing here
taskQuery.where(builder.equal(taskTable.get(TaskType_.ID).get("status"), "RECEIVED"));
List<Task> loadedTasks= session.createQuery(taskQuery).getResultList();
session.getTransaction().commit();
return loadedTasks;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
This is the TaskType class:
@Entity(name = "TaskType")
@Table(name = "task_types")
public class TaskType implements Serializable {
private final SimpleIntegerProperty id = new SimpleIntegerProperty();
private final SimpleStringProperty name = new SimpleStringProperty();
@Id
@Column(name = "task_type_id", unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
@Column(name = "task_type_name", unique = true)
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public SimpleIntegerProperty idProperty() {
return id;
}
public SimpleStringProperty nameProperty() {
return name;
}
And this is the Task class which contains a task type object:
@Entity(name = "Task")
@Table(name = "tasks")
public class Task implements Serializable {
private final SimpleIntegerProperty id = new SimpleIntegerProperty();
private final SimpleStringProperty name = new SimpleStringProperty();
private TaskType type;
@Id
@Column(name = "task_id", unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
@Column(name = "task_name", unique = true)
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "task_type_id")
public TaskType getType() {
return type;
}
public void setType(TaskType type) {
this.type = type;
}
public SimpleStringProperty nameProperty() {
return name;
}
public SimpleIntegerProperty idProperty() {
return id;
}
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?
I tried to look the exception up but I could not find any solution or understand how to apply it to my situation.
Thanks for any help!
</details>
# 答案1
**得分**: 2
`fetch`方法和`join`方法一样,仅适用于关联操作。
您可以使用以下方法替代:
```java
taskTable.fetch(Task_.TYPE, JoinType.LEFT);
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
taskTable.fetch(Task_.TYPE, JoinType.LEFT);
taskQuery.where(builder.equal(taskTable.get(Task_.TYPE).get("status"), "RECEIVED"));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论