JPA:我应该如何注释这个Map集合?

时间:2017-08-30 01:21:31

标签: java hibernate jpa java-ee eclipselink

我将通过给你一个描述性的例子来解释自己。假设我们正在使用JPA编写一个非常简单的云存储,因此我们有两个主要类,UserFile编码如下:

class User {
       List<File> ownFiles;
       Map<File, Integer> sharedFiles; 
}

class File {
       User author;
       Map<User, Integer> sharedUsers;
}

我应该如何为这些字段添加注释?我已经尝试过了,但是对于列,我总是得到NotSerializableException “数据太长了。

  • 顺便说一句,File只是一个例子,我真正的班级很小,只有一些字符串组成。所以我很确定NotSerializableException因为Map注释而被抛出。

  • 顺便说一下,这里有地图值的含义,

    • User的情况下,文件的Integer值表示用户对文件的权限级别
    • File的情况下,密钥是已共享文件的用户,而值是该用户在File
    • 上的权限级别

P.S:我正在使用Eclipselink

2 个答案:

答案 0 :(得分:1)

正如评论中所述,地图&lt;&gt; JPA 1.0 无法以这种方式处理(因此尝试序列化)

JPA 2.0添加了注释,有许多复杂的篇幅,微妙的属性(个人观点) https://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/ElementCollections 我并不惊讶生成的数据库可以是simmilar

在我看来,我可以用JPA 1方式更好地控制数据库(对我来说更清洁)。让我来表明我的建议。

我在1.x哲学中清除你的逻辑结构是:

class User {
     // ... fields waht You want
}

class FileEtiquette  {
       User author;
}

class SharingIncident {
  User user;
  FileEtiquette  file;
  int level;
}

也许我完全不理解你的命名法,所以名字可能不优雅。

下一次尝试,未编译,仅示例。

    @Entity
    class User {
        @Id
        int id;
        @Basic
        Set<SharingIncident> shares;
        @Basic
        Set<FileEtiquette> myFiles;
         // ... fields waht You want
    }

@Entity
class FileEtiquette  {
    @Id
    int id;
    @Basic
    Set<SharingIncident> sharedBy;
    User author;
}

@Entity
class SharingIncident {
    @Id
    int id;
    User user;
    FileEtiquette  file;
    int level;
}

几句话。

  • 很多人可以自动实现&#39;方式,但在你的 示例整数字段很有意思,值得设计关系 手动。
  • 通常当普通程序员认为List<>时,JPA Set<>可以 更好
  • 更改您的File名称是我的个人品味
  • 根据我对你的意图的理解,它只是基础,许多可能的改进。我的目标是展示如何取代Map&lt;&gt;以经典的方式

接下来的步骤,让我想一下

答案 1 :(得分:0)

基于this tutorial我按以下方式注释了字段:

class User {
       @OneToMany
       List<File> ownFiles;

       @ElementCollection
       Map<File, Integer> sharedFiles; 
}

class File {
       @ManyToOne
       User author;

       @ElementCollection
       Map<User, Integer> sharedUsers;
}

更详细:

class User {
       @OneToMany
       @JoinTable(name = "USER_HAS__OWN_FILES", joinColumns = {
       @JoinColumn(name = "AUTHOR", referencedColumnName = "USERNAME")}, 
            inverseJoinColumns = {@JoinColumn(name = "OWN_FILE_ID", referencedColumnName = "ID") })
       List<File> ownFiles;

       @ElementCollection
       @CollectionTable(name = "USER_HAS_SHARED_FILES", joinColumns = 
       @JoinColumn(name = "USERNAME", referencedColumnName = "USERNAME"))
       @MapKeyJoinColumn(name = "SHARED_FILE_ID", referencedColumnName = "ID")
       @Column(name = "PERMISSION_LEVEL")
       Map<File, Integer> sharedFiles; 
}

class File {
       @ManyToOne
       @JoinColumn(name = "FILE_AUTHOR", referencedColumnName = "USERNAME")
       User author;

       @ElementCollection
       @CollectionTable(name = "FILE_HAS_BEEN_SHARED_TO_USER", 
           joinColumns = @JoinColumn(name = "FILE_ID", referencedColumnName = "ID"))
       @MapKeyJoinColumn(name = "USER_THAT_FILE_HAS_BEEN_SHARED_TO", referencedColumnName = "USERNAME")
       @Column(name = "PERMISSION_LEVEL")
       Map<User, Integer> sharedUsers;
}

现在它按预期工作,生成以下表格:

  • User (ID, Username, ...)
  • File (ID, Filename, Author, ...)
  • User_has_shared_files (Username, Shared_file_id, permission_level)
  • User_has__own_files (Username, Own_file_id)
  • File_has_been_shared_to_user (File_id, Username_id, permission_level)

@ElementCollection注释对于映射Java.Map<Entity, basicType>

非常有用