首页 > 解决方案 > 在 Hibernate 中扩展/修改生成的实体

问题描述

我正在为 mysql 数据库创建 REST api 服务。我使用 IntelliJ 的持久性工具生成了类。它做得很好。

我正在使用的架构有一些怪癖。用户希望端点可以被“id”主键列以外的其他属性访问。

例如:/object/<name property>' versus/对象/`。

不过,这就是问题所在。架构可以更改。name 属性不会去任何地方,所以我可以放心地假设它总是在对象上。

我了解到您可以使用超类来强制这些生成的实体具有自定义属性,而不会影响数据库模式。我不想在生成的实体中进行模型更改并更新数据库表布局,因为它不是我的数据库。

我有一门叫动物的课。

    @Entity
    @Table(name = "animals", schema = "xyz123", catalog = "")
    public class AnimalEntity extends AnimalSuperclass {
        private Integer id;
        private String name;
        private String description;

        @Id
        @Column(name = "id", nullable = false)
        public Integer getId() {
            return id;
        }

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

        @Basic
        @Column(name = "name", nullable = true, length = 80)
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Basic
        @Column(name = "description", nullable = true, length = 255)
        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            RoleEntity that = (RoleEntity) o;
            return Objects.equals(id, that.id) &&
                    Objects.equals(name, that.name) &&
                    Objects.equals(description, that.description);
        }

        @Override
        public int hashCode() {

            return Objects.hash(id, name, description);
        }
    }

我必须手动添加扩展 AnimalSuperclass。目前这很好。最终,我将尝试在运行时使用 .xmls 生成这些。

然后我有这个超类..

    @MappedSuperclass
    public class AnimalSuperclass implements Serializable  {
        private String testMessage;
        private String name;
        private Integer id;

        @Transient
        public String getTestMessage() {
            return this.testMessage;
        }

        public void setTestMessage(String id) {
            this.testMessage = testMessage;
        }
    }

我想要做的是强制@Id注释在超类中的 name 属性上。像这样的东西.. @MappedSuperclass public class AnimalSuperclass implements Serializable { private String testMessage; 私有字符串名称;私人整数 id;

        @Transient
        public String getTestMessage() {
            return this.testMessage;
        }

        public void setTestMessage(String id) {
            this.testMessage = testMessage;
        }

        @Basic
        @Id
        @Column(name = "name", nullable = false, length = 15)
        private String getName() {
            return name;
        }

        private void setName(String name) {
            this.name = name;
        }


        @NaturalId
        @Column(name = "id", nullable = false)
        private Integer getId() {
            return id;
        }

        private void setId(Integer id) {
            this.id = id;
        }
    }

我该怎么做呢?目前,当我到达端点时,这会引发错误:{"cause":null,"message":"Id must be assignable to Serializable!: null"}

Java 不是我的第一语言,所以无论如何我都不是专家。但是从我读过的内容来看,不可能从超类中覆盖子类属性。有没有更好的方法来解决这个问题,也许是使用RepositoryRestConfiguration?我PagingAndSortingRepository用来为这些实体服务。我无法扩展实体并将我的超类用作子类,因为这会dType在架构中创建一个属性,并且我无法更改表布局。

标签: javaspringhibernatejpa

解决方案


请求与您的实体之间没有硬链接。在您的存储库中,您可以编写可以查询从请求中获取的数据的方法。

例如,如果他们要求一个名字,你可以做类似的事情

Page<AnimalEntity> findByName(String name, Pageable pageable);

在您的存储库中。Spring 将负责其余的工作,然后您可以在控制器中调用它。

@Service
public class AnimalService {
  @Autowired
  private AnimalEntityRepository animalRepo;


  public Page<AnimalEntity> findAnimal(String name) {

    Page<AnimalEntity> animals = animalRepo.findByName(name, new PageRequest(1,20));

    return animals;
  }
}

需要提到的一件事是,根据您在将实体发送回客户端并且实体被序列化时配置 Hibernate 的方式,您可能会遇到延迟初始化失败的错误。如果是这种情况,您的实体将必须转换为 POJO(普通的旧 java 对象)并将其发回。


推荐阅读