代码之家  ›  专栏  ›  技术社区  ›  smeeb

Hibernate/JPA将列映射到映射类型

  •  1
  • smeeb  · 技术社区  · 6 年前

    这里有Spring Boot、Hibernate/JPA和MySQL。我有下表:

    CREATE TABLE IF NOT EXISTS fizzbuzzes (
        fizzbuzz_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        fizzbuzz_type_a VARCHAR(250) NOT NULL,
        fizzbuzz_type_b VARCHAR(250) NOT NULL,
        fizzbuzz_type_c VARCHAR(250) NOT NULL,
        fizzbuzz_type_d VARCHAR(250) NOT NULL,
        fizzbuzz_type_e VARCHAR(250) NOT NULL,
        fizzbuzz_type_f VARCHAR(250) NOT NULL,
        fizzbuzz_type_g VARCHAR(250) NOT NULL,
        fizzbuzz_type_h VARCHAR(250) NOT NULL,
        fizzbuzz_type_i VARCHAR(250) NOT NULL,
        fizzbuzz_type_j VARCHAR(250) NOT NULL,
        fizzbuzz_type_k VARCHAR(250) NOT NULL,
        fizzbuzz_type_l VARCHAR(250) NOT NULL,
        fizzbuzz_type_m VARCHAR(250) NOT NULL,
        fizzbuzz_type_n VARCHAR(250) NOT NULL,
        fizzbuzz_type_o VARCHAR(250) NOT NULL,
        fizzbuzz_type_p VARCHAR(250) NOT NULL,
    
        CONSTRAINT pk_fizzbuzzes PRIMARY KEY (fizzbuzz_id);
    );
    

    我希望此表O/R映射到具有 Map<String,String> 保持A型到P型的嘶嘶声。

    因此,与您通常看到的不同:

    @Entity
    @Table(name = "fizzbuzzes")
    public class Fizzbuzz {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "fizzbuzz_type_a")
        private String typeA;
    
        @Column(name = "fizzbuzz_type_a")
        private String typeB;
    
        // ...
    
        @Column(name = "fizzbuzz_type_a")
        private String typeP;
    
        // Getters, setters & ctors
    }
    

    。。。相反,我想:

    @Entity
    @Table(name = "fizzbuzzes")
    public class Fizzbuzz {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "???")
        private Map<String,String> types;
    
        // Getters, setters & ctors
    }
    

    其中 types 可能是硬编码字符串 typeA ,则, typeB 。。。, typeP 以及 类型 将是DB表中各列的值。

    这有可能做到吗?如果有,如何做到?

    1 回复  |  直到 6 年前
        1
  •  5
  •   Tirath    6 年前

    差不多吧。如果您同意将类型值放在单独的表中,则可以这样做。然后您可以使用 @ElmentCollection @MapKeyColumn

    例如:

    @ElementCollection
    @MapKeyColumn(name="type_key")
    @Column(name="type_value")
    @CollectionTable(name="fizzbuzz_types", joinColumns=@JoinColumn(name="fizzbuzz_id"))
    Map<String, String> types= new HashMap<>(); 
    

    否则,您需要像在第一个示例中一样对类型列进行硬编码,并且可以添加 @PostLoad @PrePersist 钩子用于将静态列转换为瞬态映射或从瞬态映射转换为静态列。

    类似于:

    @Entity
    @Table(name = "fizzbuzzes")
    public class Fizzbuzz {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "fizzbuzz_type_a")
        private String typeA;
    
        @Column(name = "fizzbuzz_type_a")
        private String typeB;
    
        @Transient
        private Map<String, String> types = new HashMap<>();
    
        @PostLoad
        public void toMap() {
           this.types.put("typeA", this.typeA);
           this.types.put("typeB", this.typeB);
        }
        @PrePersist
        public void fromMap() {
           this.typeA = this.types.get("typeA");
           this.typeB= this.types.get("typeB");
        }
    }