การจัดเก็บแผนที่ <String, String> โดยใช้ JPA


103

ฉันสงสัยว่าเป็นไปได้หรือไม่โดยใช้คำอธิบายประกอบเพื่อคงattributesแผนที่ในชั้นเรียนต่อไปนี้โดยใช้ JPA2

public class Example {
    long id;
    // ....
    Map<String, String> attributes = new HashMap<String, String>();
    // ....
}

เนื่องจากเรามีฐานข้อมูลการผลิตที่มีอยู่แล้วดังนั้นค่าของattributes สามารถจับคู่กับตารางที่มีอยู่ต่อไปนี้:

create table example_attributes {
    example_id bigint,
    name varchar(100),
    value varchar(100));

คำตอบ:


201

JPA 2.0 รองรับคอลเลกชันของดั้งเดิมผ่าน@ElementCollectionคำอธิบายประกอบที่คุณสามารถใช้ร่วมกับการสนับสนุนjava.util.Mapคอลเลกชัน สิ่งนี้ควรใช้งานได้:

@Entity
public class Example {
    @Id long id;
    // ....
    @ElementCollection
    @MapKeyColumn(name="name")
    @Column(name="value")
    @CollectionTable(name="example_attributes", joinColumns=@JoinColumn(name="example_id"))
    Map<String, String> attributes = new HashMap<String, String>(); // maps from attribute name to value

}

ดูเพิ่มเติม (ในข้อกำหนด JPA 2.0)

  • 2.6 - คอลเล็กชันของคลาสฝังตัวและประเภทพื้นฐาน
  • 2.7 แผนที่คอลเลกชัน
  • 10.1.11 - คำอธิบายประกอบ ElementCollection
  • 11.1.29 คำอธิบายประกอบ MapKeyColumn

1
มีวิธีแก้ไขโดยใช้ JPA 1 หรือไม่ ฉันพบเฉพาะตัวอย่างของMap<String, SomeOtherClass>
L. Holanda

3
อาจจะคุ้มค่าที่จะกล่าวถึงว่าexample_attributesควรมีคีย์คอมโพสิต(example_id, name)ซึ่งเป็นสิ่งที่ hbm2ddl จะสร้างจากด้านบน
James Bassett

ฉันลองตัวอย่างข้างต้นแล้ว แต่เมื่อพยายามคงเอนทิตีฉันได้รับข้อยกเว้น: คุณต้องกำหนดการแมปอย่างน้อยหนึ่งรายการสำหรับตารางนี้ แบบสอบถาม: InsertObjectQuery (null) คำแนะนำใด ๆ ? ฉันสร้างเอนทิตีว่างและตั้งค่าแมพคุณสมบัติแล้วพยายามคงอยู่
Kamila

2
เมื่อใช้ MariaDB ฉันพบว่าSpecified key was too long; max key length is 767 bytesทำสิ่งนี้ คีย์หลักที่พยายามสร้างคือการรวมกันของ varchar (255) และ @JoinColumn ซึ่งเกินขนาดคอลัมน์เริ่มต้น คุณต้องเปลี่ยนฐานข้อมูลของคุณหรือแก้ไข @MapKeyColumn ของคุณเพื่อระบุความยาว:@MapKeyColumn(name="name", length=100)
จอน

18
  @ElementCollection(fetch = FetchType.LAZY)
  @CollectionTable(name = "raw_events_custom", joinColumns = @JoinColumn(name =     "raw_event_id"))
  @MapKeyColumn(name = "field_key", length = 50)
  @Column(name = "field_val", length = 100)
  @BatchSize(size = 20)
  private Map<String, String> customValues = new HashMap<String, String>();

นี่คือตัวอย่างวิธีตั้งค่าแผนที่โดยควบคุมชื่อคอลัมน์และตารางและความยาวของฟิลด์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.