Обработка наследования сущностей Spring Boot

Я работаю с этим руководство для обработки наследования сущностей. У меня есть лица и компании, которые расширяют сущность User.

@Entity
@Inheritance
public abstract class User { 

@Id
private long id;

@NotNull
private String email;

// getters and settres
}

@Entity
public class Person extends User { 
private int age;
// getters and settres and other attributs
}

@Entity
public class Company extends User { 
private String companyName;
// getters and settres and other attribut
}

затем UserRpository, PersonRepository и Company Repository, которые расширяют UserBaseRepository.

@NoRepositoryBean
public interface UserBaseRepository<T extends User> 
extends CrudRepository<T, Long> {

public T findByEmail(String email);

}

@Transactional
public interface UserRepository extends UserBaseRepository<User> { }

@Transactional
public interface PersonRepository extends UserBaseRepository<Person> { }

@Transactional
public interface CompanyRepository extends UserBaseRepository<Company> { }

Проблема заключается в том, что при вызове personRepository.findAll (), чтобы получить всех людей, в результате я получил также компании.

Я клонировал проект из учебника, и все работает, как ожидалось. Как выглядит SQL, который генерирует Hibernate? А какую версию Spring вы используете?

Simon Martinelli 02.11.2018 11:06
2
1
7 261
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша проблема связана с столбцом «Дискриминатор», который требуется JPA. Вы используете аннотацию @Inheritance и по умолчанию будет использовать стратегию InheritanceType.SINGLE_TABLE. Это означает следующее:

  1. Ваши унаследованные объекты Person и Company войдут в одну таблицу.
  2. JPA потребуется Дискриминатор для различения типов сущностей.

Я сделал следующее, чтобы он работал в вашем случае:

Сущности:

@Inheritance
@Entity
@Table(name = "user_table")
public abstract class User {

    @Id
    private long id;

    @NotNull
    @Column
    private String email;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

@Entity
public class Company  extends User {

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

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }
}

@Entity
public class Person extends User {

    @Column
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Схема БД:

-- user table
create table user_table (
  id BIGINT         NOT NULL PRIMARY KEY,
    email             VARCHAR(50) NOT NULL,
    age               INT,
    company_name      VARCHAR(50),
    dtype             VARCHAR(80) -- Discriminator
);

Некоторые тестовые данные:

insert into user_table(id, dtype, age, email) values
(1,'Person', 25, '[email protected]'),
(2,'Person',22, '[email protected]');

insert into user_table(id, dtype, company_name, email) values
(3,'Company','Acme Consultants', '[email protected]'),
(4,'Company', 'Foo Consultants', '[email protected]');

Репозитории:

@NoRepositoryBean
public interface UserBaseRepository<T extends User> extends CrudRepository<T, Long> {

    T findByEmail(String email);
}

@Transactional
public interface PersonRepository extends UserBaseRepository<Person> {

}

@Transactional
public interface CompanyRepository extends UserBaseRepository<Company> {

}

Тесты JUnit:

public class MultiRepositoryTest extends BaseWebAppContextTest {

    @Autowired
    private PersonRepository personRepository;

    @Autowired
    private CompanyRepository companyRepository;

    @Test
    public void testGetPersons() {
        List<Person> target = new ArrayList<>();
        personRepository.findAll().forEach(target::add);
        Assert.assertEquals(2, target.size());
    }
    @Test
    public void testGetCompanies() {
        List<Company> target = new ArrayList<>();
        companyRepository.findAll().forEach(target::add);
        Assert.assertEquals(2, target.size());
    }

}

Вышеуказанные тесты проходят. Это означает, что JPA теперь правильно использует дискриминатор для извлечения требуемых записей.

Теорию, связанную с JPA для вашего вопроса, см. В этом ссылка.

@Achraf, если это сработало для вас, не могли бы вы принять это как ответ?

Arun Patra 02.11.2018 14:25

Другие вопросы по теме