Как мне использовать и сопоставлять внутренний класс в качестве переменной поля столбца в Spring Boot?

#java #spring #database #spring-boot #hibernate

#java #spring #База данных #spring-boot #спящий режим

Вопрос:

Я получаю сообщение об ошибке, которое я сузил до того, что один из типов столбцов слишком сложный : (List<Foo>) . Как я могу правильно использовать свой внутренний класс в качестве типа столбца?

Вот соответствующий фрагмент кода моей модели:

Users.java

 @Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

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

@Column(name = "password")
private String password;

@Column(name = "todos")
private List<TodoItem> todos = new ArrayList<TodoItem>();

public static class TodoItem {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected long id;
    protected String todo;
    protected boolean completed;

    public TodoItem() {}

    public TodoItem(String todo, boolean completed) {
        // super();
        this.todo = todo;
        this.completed = completed;
    }
}

public User(String name, String password, List<TodoItem> todos) {
    super();
    this.name = name;
    this.password = password;
    this.todos = todos;
}
 

И вот соответствующий вывод ошибки, который я получаю:

Журнал консоли

 2021-01-15 01:18:30.966 ERROR 1480 --- [           main] j.LocalContainerEntityManagerFactoryBean : 
Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate 
SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: 
java.util.List, at table: users, for columns: [org.hibernate.mapping.Column(todos)]
2021-01-15 01:18:30.967  WARN 1480 --- [           main] ConfigServletWebServerApplicationContext : 
Exception encountered during context initialization - cancelling refresh attempt: 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'entityManagerFactory' defined in class path resource 
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init 
method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] 
Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could 
not determine type for: java.util.List, at table: users, for columns: 
[org.hibernate.mapping.Column(todos)]
Error starting ApplicationContext. To display the conditions report re-run your application with 
'debug' enabled.
2021-01-15 01:18:31.004 ERROR 1480 --- [           main] o.s.boot.SpringApplication               : 
Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'entityManagerFactory' defined in class path resource 
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init 
method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] 
Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could 
not determine type for: java.util.List, at table: users, for columns: 
[org.hibernate.mapping.Column(todos)]
 

Я начинаю думать, что это может быть невозможно, и мне нужно создать внутренний класс в виде отдельной таблицы

Комментарии:

1. внутренний класс должен быть статическим?

2. попробуйте связать TodoItem и todos с @OneToMany

Ответ №1:

Попробуйте

 import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

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

    @Column(name = "password")
    private String password;

    @OneToMany
    @JoinColumn(name = "user_id")
    private List<TodoItem> todos = new ArrayList<>();

    public User() {}

    public User(String name, String password, List<TodoItem> todos) {
        this.name = name;
        this.password = password;
        this.todos = todos;
    }

    @Entity
    @Table(name = "todo_item")
    public static class TodoItem {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        protected long id;

        @Column(name = "todo")
        protected String todo;
        
        @Column(name = "completed")
        protected boolean completed;

        public TodoItem() {
        }

        public TodoItem(String todo, boolean completed) {
            this.todo = todo;
            this.completed = completed;
        }

        // getter/setter ..
    }

    // getter/setter ..
}