将实体的字段更改为其他类型的字段

时间:2019-07-09 07:28:15

标签: java spring-boot jpa h2 polymorphic-associations

基本上可以说我有一堂课-汽车。 此类汽车有一个“用户”字段。现在有不同类型的用户-假设“推销员”,“出租车司机”,“检查员”。所有这些都是它们自己的类,从长远来看,它们将具有不同的字段。 现在,我们说这辆车被卖了,那么车主就得换车了。现在出现了问题-为了更改所有者,用户类上的“所有者”字段必须是常规名称-它不能是“推销员”,因为我将如何将所有者更改为“出租车司机”。 我听说过围绕该主题使用多态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”])

1 个答案:

答案 0 :(得分:0)

您可以使用参数化创建jpa存储库

public interface OwnerRepository extends JpaRepository<Owner, Long>

find()将返回Salseman类型,已擦除为Owner类型。如果要再创建一个扩展Owner的类,则在调用Examiner时说findAll,jpa将返回OwnerExaminer混合在一起的列表,擦除为父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)。