簡體   English   中英

mysql:為什么我需要在enum上使用AttributeConverter才能將具有enum數據類型的數據庫列映射為帶有JPA實體的enum?

[英]mysql : why would I require AttributeConverter over enum to map a DB column having enum datatype as enum with a JPA entity?

我有一個user數據庫表為:

CREATE TABLE IF NOT EXISTS `user` (
  `user_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `first_ name` VARCHAR(45) NOT NULL,
  `active_status` ENUM('ACTIVE', 'PENDING', 'DEACTIVATED', 'BLOCKED', 'SPAM', 'DELETED') NOT NULL ,
  UNIQUE INDEX `unique_id_UNIQUE` (`unique_id` ASC),
  UNIQUE INDEX `email_UNIQUE` (`email` ASC),
  PRIMARY KEY (`user_id`))
ENGINE = InnoDB;    

我將其映射為相應的JPA實體類,如下所示:

@Entity
public class User implements OfloyEntity {

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "user_id", unique = true, nullable = false)
private int userId;

//other fields

@Enumerated(EnumType.STRING)
@Column(name = "active_status", nullable = false, length = 11)
private UserStatus activeStatus;

如您所見,我已經將activeStatus映射到一個enum UserStatus以限制持久層本身的整體。

public enum UserStatus {

    ACTIVE,
    PENDING,
    DEACTIVATED,
    BLOCKED,
    DELETED,
    SPAM
}

我想知道使用這種方法在持久層中實現數據庫枚舉是否有任何缺點? 我扔了多篇推薦使用AttributeConverter的文章,但是由於枚舉中的值非常有限且修改的機會較小,因此我無法將所有這些文章與我的要求聯系起來。

是否有我缺少的東西,或者可以對我的設計進行任何改進?

我丟的文章:
紫杉
thorban和其他一些stackoverflow問題。

更新 :閱讀Jens的答案后,我決定實現AttributeConverter (針對用戶的gender )。 這讓我有些困惑:
為什么我決定使用enum作為MYSQL列類型 :因為它限制了值並需要較少的空間。 因為MYSQL將其枚舉的序數值存儲在幕后,並且當要求提供它的String值時,它節省了空間。
我對性別的實現:

public enum UserGender {

    MALE('M'),
    FEMALE('F'),
    OTHER('O');

    private Character shortName;

    private UserGender(Character shortName) {
        this.shortName = shortName;
    }

    public Character getShortName() {
        return shortName;
    }

    public static UserGender fromShortName(Character shortName) {
        switch (shortName) {
        case 'M': return UserGender.MALE;

        case 'F' : return UserGender.FEMALE;

        case 'O' : return UserGender.OTHER;

        default:
            throw new UserGenderNotSupportedException("user gender with shortName : " + shortName + " not supported");
        }

    }

}

轉換器類別:

@Converter(autoApply = true)
public class UserGenderConverter implements AttributeConverter<UserGender, Character> {

    @Override
    public Character convertToDatabaseColumn(UserGender userGender) {
        return userGender.getShortName();
    }

    @Override
    public UserGender convertToEntityAttribute(Character dbGender) {
        return UserGender.fromShortName(dbGender);
    }

}

現在,主要的疑問
1.根據博客,在數據庫中使用MYSQL enum是邪惡的,因為總有一天,如果我需要向枚舉列添加額外的值,這將需要一個表ALTER,但使用AttributeConverter情況不一樣嗎? 因為這里也使用了java enum ,如果有朝一日需要新的性別,那將需要更改?
2.如果使用AttributeConverter ,則必須在某個地方記錄Java enum (此處為UserGender )說明,以便DBA可以理解F,M,O代表什么。 我在這里嗎?

這些文章為您提供了許多潛在的弊端:

使用@Enumerated(EnumType.STRING)具有以下內容:

  • 與其他選項相比,它占用了大量空間。 請注意,這意味着需要通過電線加載和傳輸更多數據,這也會影響性能。 我們不知道這是否對您造成問題,並且在進行了一些性能測試之前,您也不知道。
  • 將枚舉值的名稱與列值緊密聯系在一起。 這可能是有風險的,因為開發人員習慣於快速重命名內容,並且您需要使用實際的舊有數據進行測試才能捕捉到這一點。

如果您不使用真正大量的數據來更新所有行的列,這是一個實際的問題,那我就不會費心。 當簡單的解決方案實際上成為問題時,引入AttributeConverter並更新數據就很容易了。

有關更新的問題的更新:

  1. 我不認為任何東西都是“邪惡的”,因為它可能需要ALTER TABLE語句。 通過這種說法,我們應該完全廢除關系數據庫,因為使用關系數據庫需要DDL,而應用程序的演進將需要更多的關系數據庫。 當然,DDL語句的必要性使部署更加復雜。 但是無論如何,您都需要能夠處理此問題。

    但是的確,在這種情況下,使用AttributeConverter不需要任何DDL,因為您只需要在同一列中放入另一個值即可,該值沒有任何特殊限制,但該值的最大長度除外。 假設您在該列上沒有檢查約束來限制合法值。

    1. 您是否需要記錄Enum與數據庫中存儲的值之間的關系? 取決於您的團隊。 DBA甚至關心數據的含義嗎? DBA是否具有訪問權限和掌握Java代碼的技能? 如果DBA需要或想要知道並且無法或不會從源代碼中獲取信息,則必須對其進行記錄。 真正。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM