Ваша проблема связана со столбцом «Дискриминатор», который требуется JPA. Вы используете аннотацию @Inheritance
и по умолчанию будете использовать стратегию InheritanceType.SINGLE_TABLE
. Это означает следующее:
- Ваши унаследованные сущности
Person
и Company
войдут в одну таблицу.
- JPA потребует, чтобы дискриминатор различал типы сущностей.
Я сделал следующее, чтобы он работал для вашего варианта использования:
Entities:
@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, 'john.doe@email.com'),
(2,'Person',22, 'jane.doe@email.com');
insert into user_table(id, dtype, company_name, email) values
(3,'Company','Acme Consultants', 'acme@company.com'),
(4,'Company', 'Foo Consultants', 'foo@company.com');
Хранилища:
@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 по вашему вопросу смотрите по этой ссылке .