DddoubleChin
DddoubleChin

Reputation: 65

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

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!

Upvotes: 1

Views: 656

Answers (1)

Christian Beikov
Christian Beikov

Reputation: 16400

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"));

Upvotes: 2

Related Questions