基本上可以说我有一堂课-汽车。 此类汽车有一个“用户”字段。现在有不同类型的用户-假设“推销员”,“出租车司机”,“检查员”。所有这些都是它们自己的类,从长远来看,它们将具有不同的字段。 现在,我们说这辆车被卖了,那么车主就得换车了。现在出现了问题-为了更改所有者,用户类上的“所有者”字段必须是常规名称-它不能是“推销员”,因为我将如何将所有者更改为“出租车司机”。 我听说过围绕该主题使用多态db和morphing的术语,但老实说,我不知道如何解决此问题。
我查阅了一份指南,它的建议在某种程度上奏效了。它所做的是创建一个抽象类“所有者”,并创建“检查者”,“推销员”,“出租车司机”类,以扩展该抽象类。抽象类将继承与single_table一起使用,在这种情况下,将创建一个表,其中存储了所有扩展所有者的类,并且可以通过“类型”列来区分它们。 通过jpa保存实体在此解决方案中可以很好地工作,但是当我想通过其ID查找所有者时,它不起作用,可能是因为我的JpaRepository试图将db行映射到类Owner,但是由于Owner是抽象类,它无法创建它的实例。
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType =
DiscriminatorType.STRING)
public abstract class Owner {
@Id
@GeneratedValue
private Long id;
}
@Entity
@Data
@DiscriminatorValue("salesman")
public class Salesman extends Owner {
@Id
@GeneratedValue
private Long id;
private Long balance;
}
@Repository
public interface OwnerRepository extends JpaRepository<Owner, Long> {
}
@Service
public class OwnerService {
@Autowired
private OwnerRepository repo;
public Owner getById(Long id) {
return repo.getOne(id);
}
}
我希望能够更改汽车的用户并对其进行简单的CRUD操作。
当前,当我尝试使用JpaRepository方法getOne()时收到以下错误: 路径为[]的Servlet [dispatcherServlet]的Servlet.service()抛出异常[请求处理失败;嵌套的异常是org.springframework.http.converter.HttpMessageConversionException:类型定义错误:[简单类型,类org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor];嵌套的异常是com.fasterxml.jackson.databind.exc.InvalidDefinitionException:没有为类org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor找到序列化器,也没有发现创建BeanSerializer的属性(为避免异常,请禁用SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过参考链:具有根本原因的ee.priit.polymorphism.model.Owner $ HibernateProxy $ GnSnpo6f [“ hibernateLazyInitializer”])]]
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:未找到类org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor的序列化器,也未发现创建BeanSerializer的属性(为避免异常,请禁用SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过参考链:ee.priit.polymorphism.model.Owner $ HibernateProxy $ GnSnpo6f [“ hibernateLazyInitializer”])
答案 0 :(得分:0)
您可以使用参数化创建jpa存储库
public interface OwnerRepository extends JpaRepository<Owner, Long>
find()
将返回Salseman
类型,已擦除为Owner
类型。如果要再创建一个扩展Owner
的类,则在调用Examiner
时说findAll
,jpa将返回Owner
和Examiner
混合在一起的列表,擦除为父Owner
类型。至少它是最新的jpa + hibernate版本。
在数据提取期间,jpa(休眠)会根据Discriminator列值确定目标实体类型,并相应地创建目标实体类型。
如果您想获取所有Owner
,但仅获取Owner
参数化的Salesman
,例如
public interface OwnerRepository extends JpaRepository<Salesman, Long>
可以解决问题。
如果您尝试启用
spring:
jpa:
properties:
hibernate:
show_sql: true
format_sql: true
... hibernate sql输出,您将找到确切的选择查询结构。 (因为您要求jpa,所以我假设您使用spring或spring boot)。