I will explain myself by giving you a descriptive example. Let's say we are programming a very simple Cloud Storage using JPA, so we have two main classes, User
and File
coded as follows:
class User {
List<File> ownFiles;
Map<File, Integer> sharedFiles;
}
class File {
User author;
Map<User, Integer> sharedUsers;
}
How should I annotate this fields? I've tried, but I always get NotSerializableException
"data too long for column".
By the way, File
is just an example, my real class is small, only composed of some Strings. So I'm pretty sure the NotSerializableException
is thrown because of the Map annotations.
By the way, here you have the meaning of the Maps values,
User
, the Integer value of the files is representing the permission level of the user over the fileFile
the Keys are those Users who the file has been shared to and the Value is the permission level of that User over the File
P.S: I'm using Eclipselink
Based on this tutorial I annotated the fields in the following way:
class User {
@OneToMany
List<File> ownFiles;
@ElementCollection
Map<File, Integer> sharedFiles;
}
class File {
@ManyToOne
User author;
@ElementCollection
Map<User, Integer> sharedUsers;
}
More detailed:
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;
}
Now it works as I expected, generating the following tables:
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)
The @ElementCollection
annotation is useful to map Java.Map<Entity, basicType>