Following example shows how to use JPA type conversion of attributes involving embeddable key or value of a Map.
When the @Convert annotation is used on a map containing instances of embeddable classes, the attributeName element must be specified, and "key." or "value." must be used to prefix the name of the attribute that is to be converted. Let's understand that with an example.
Example
The Converter
@Converter
public class FileConverter implements AttributeConverter<File, String> {
@Override
public String convertToDatabaseColumn(File attribute) {
return attribute.getAbsolutePath();
}
@Override
public File convertToEntityAttribute(String dbData) {
return new File(dbData);
}
}
The Entity
@Entity
public class Journal {
@Id
@GeneratedValue
private long id;
@ElementCollection
@Convert(converter = FileConverter.class, attributeName = "value.file")
private Map<String, Report> reportMap;
.............
public void addReport(String reportName, String description, File file) {
if (reportMap == null) {
reportMap = new HashMap<>();
}
Report report = new Report();
report.setDescription(description);
report.setFile(file);
reportMap.put(reportName, report);
}
.............
}
@Embeddable
public class Report {
private String description;
private File file;
.............
}
The main class
When persisting a Map with @ElementCollection , the entity and the map are persisted to two separate foreign/primary-key tables (check out the related tutorial here).
public class ExampleMain {
private static EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("example-unit");
public static void main(String[] args) {
try {
nativeQuery("Show Columns from Journal");
nativeQuery("Show Columns from Journal_ReportMap");
persistEntity();
nativeQuery("Select * from Journal");
nativeQuery("Select * from Journal_ReportMap");
loadEntity();
} finally {
entityManagerFactory.close();
}
}
public static void persistEntity() {
Journal journal = new Journal();
journal.addReport("name1", "test report 1", new File("c:/temp/report-1.txt"));
journal.addReport("name2", "test report 2", new File("c:/temp/report-2.txt"));
System.out.println("Persisting journal: " + journal);
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.persist(journal);
em.getTransaction().commit();
em.close();
}
private static void loadEntity() {
EntityManager em = entityManagerFactory.createEntityManager();
Journal journal = em.find(Journal.class, 1L);
System.out.println("Journal loaded: " + journal);
em.close();
}
public static void nativeQuery(String s) {
EntityManager em = entityManagerFactory.createEntityManager();
System.out.printf("'%s'%n", s);
Query query = em.createNativeQuery(s);
List list = query.getResultList();
for (Object o : list) {
if (o instanceof Object[]) {
System.out.println(Arrays.toString((Object[]) o));
} else {
System.out.println(o);
}
}
em.close();
}
} 'Show Columns from Journal' [ID, BIGINT(19), NO, PRI, NULL] 'Show Columns from Journal_ReportMap' [JOURNAL_ID, BIGINT(19), NO, PRI, NULL] [DESCRIPTION, VARCHAR(255), YES, , NULL] [FILE, VARCHAR(255), YES, , NULL] [REPORTMAP_KEY, VARCHAR(255), NO, PRI, NULL] Persisting journal: Journal{id=0, reportMap={name2=Report{, description='test report 2', file=c:\temp\report-2.txt}, name1=Report{, description='test report 1', file=c:\temp\report-1.txt}}} 'Select * from Journal' 1 'Select * from Journal_ReportMap' [1, test report 2, c:\temp\report-2.txt, name2] [1, test report 1, c:\temp\report-1.txt, name1] Journal loaded: Journal{id=1, reportMap={name2=Report{, description='test report 2', file=c:\temp\report-2.txt}, name1=Report{, description='test report 1', file=c:\temp\report-1.txt}}}
Example ProjectDependencies and Technologies Used: - h2 1.4.196: H2 Database Engine.
- hibernate-core 5.2.12.Final: The core O/RM functionality as provided by Hibernate.
Implements javax.persistence:javax.persistence-api version 2.1 - JDK 1.8
- Maven 3.3.9
|
|