【问题标题】:How to specify column names in Hibernate/JPA when inheritance is involved?涉及继承时如何在 Hibernate/JPA 中指定列名?
【发布时间】:2017-09-01 23:07:28
【问题描述】:

我想我想在这里吃我的蛋糕,但我们会看看是否有一个可行的解决方案来解决我正在寻找的问题。我有一个 Spring Boot/JPA/Hibernate 应用程序,它将与 MySQL 作为其后备存储进行通信。我有几种情况,从 OOP 的角度来看,我的实体类形成了这样的父/子层次结构:

// Groovy pseudo-code!
class Vehicle {
  Long id
  Long maxSpeed
  String make
  String model
}

class Motorcycle extends Vehicle {
  Boolean isTwoStroke
}

class Car extends Vehicle {
  Boolean hasLeatherInterior
}

等等。通常,在 JPA 之外,我可能会像这样设计它们各自的表:

CREATE TABLE motorcycles (
  motorcycle_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  motorcycle_max_speed BIGINT UNSIGNED,
  motorcycle_make VARCHAR(50) NOT NULL,
  motorcycle_model VARCHAR(50) NOT NULL,
  motorcycle_is_two_speed BIT NOT NULL,

  # PK, FK, UC, index constraints down here (omitted for brevity)
);

CREATE TABLE cars (
  car_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  car_max_speed BIGINT UNSIGNED,
  car_make VARCHAR(50) NOT NULL,
  car_model VARCHAR(50) NOT NULL,
  car_has_leather_interior BIT NOT NULL,

  # PK, FK, UC, index constraints down here (omitted for brevity)
);

理想情况下我想保持这个表格设计原样,“父车辆”列的名称与我上面的一样。但是,如果我正确理解了 Hibernate/JPA API,那么我不认为在不做出某种牺牲的情况下是不可能的。我认为我要么需要牺牲应用层的继承,以便我可以完全按照我在数据库中的名称命名子类中的列:

@Entity
class Motorcycle {    // No longer extends Vehicle :-(
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Column(name = "motorcycle_id")
  Long id

  @Column(name = "motorcycle_max_speed")
  Long maxSpeed

  @Column(name = "motorcycle_make")
  String make

  @Column(name = "motorcycle_model")
  String model

  @Column(name = "motorcycle_is_two_speed")
  Boolean isTwoStroke
}

@Entity
class Car {    // No longer extends Vehicle :-(
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Column(name = "car_id")
  Long id

  @Column(name = "car_max_speed")
  Long maxSpeed

  @Column(name = "car_make")
  String make

  @Column(name = "car_model")
  String model

  @Column(name = "car_has_leather_interior")
  Boolean hasLeatherInterior
}

或者我认为我可以保留应用层继承,但随后需要像这样重构我的数据库表:

CREATE TABLE motorcycles (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  max_speed BIGINT UNSIGNED,
  make VARCHAR(50) NOT NULL,
  model VARCHAR(50) NOT NULL,
  motorcycle_is_two_speed BIT NOT NULL,

  # PK, FK, UC, index constraints down here (omitted for brevity)
);

CREATE TABLE cars (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  max_speed BIGINT UNSIGNED,
  make VARCHAR(50) NOT NULL,
  model VARCHAR(50) NOT NULL,
  car_has_leather_interior BIT NOT NULL,

  # PK, FK, UC, index constraints down here (omitted for brevity)
);

所以我问:我是否可以保留我的应用层继承(并让 MotorcycleCarVehicle 继承这些属性)保留我的数据库表列使用我的首选约定命名?

【问题讨论】:

    标签: java hibernate jpa inheritance groovy


    【解决方案1】:

    可以使用@MappedSuperclass (Designates a class whose mapping information is applied to the entities that inherit from it. A mapped superclass has no separate table defined for it.) 车辆等级:

    @MappedSuperclass
    public class Vehicle {
        @Id
        @GeneratedValue
        Long id;
        Long maxSpeed;
        String make;
        String model;
    }
    

    摩托车子类

     @Entity
        @AttributeOverrides({
                @AttributeOverride(name = "id", column = @Column(name = "motorcycle_id"))
        })
        public class Motorcycle extends Vehicle {
            Boolean isTwoStroke;
        }
    

    【讨论】:

    • 感谢@Bhushan Uniyal (+1) - 如果您不介意,可以快速跟进一个问题:我计划先创建自己的数据库,然后使用 hibernate.hbm2ddl.auto = validate(而不是 create 或其他内容)别的)。我还计划在 MySQL 中将我的主键设置为 AUTO_INCREMENT 列。如果 MySQL PK 已经自动递增,并且如果我只是让 Hibernate validate 我现有的数据库,我什至需要在代码中的 PK 字段上指定 @GeneratedValue 吗?再次感谢!
    • @smeeb 是的,您可以删除@GeneratedValue,没有它也可以工作,因为您在数据库级别使用AUTO_INCREMEN 启用。 hibernate.hbm2ddl.auto = validate 也会处理您的数据库架构,所以这里没有问题
    猜你喜欢
    • 2012-07-05
    • 2012-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多