Following example shows how to use a type converter involving a collection of Embeddable.
If @Convert annotation is used on complex types, for example on a map or a collection of simple or embeddable types, then we can use its attributeName to specify on what type the converter should be applied.
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);
}
}
An embeddable
@Embeddable
public class Report {
private String description;
//@Convert(converter = FileConverter.class)
private File file;
.............
}
The Entity
@Entity
public class Journal {
@Id
@GeneratedValue
private long id;
@ElementCollection
@Convert(converter = FileConverter.class, attributeName = "file")
private List<Report> reports;
.............
}
Note that we could have used @Convert annotation directly on file field of Report embeddable, in that case we don't have to use attributeName element. This example scenario assumes that doing that is not feasible (may be we would want to use multiple embeddable of same type with different converters in the same entity).
The main class
In case of the embeddable collection, the entity and the collection are mapped to two separate foreign/primary-key tables. One for the entity and other for embeddable fields/properties values (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_Reports");
persistEntity();
nativeQuery("Select * from Journal");
nativeQuery("Select * from Journal_Reports");
loadEntity();
} finally {
entityManagerFactory.close();
}
}
public static void persistEntity() {
Journal journal = new Journal();
journal.addReport("test report 1", new File("c:/temp/report-1.txt"));
journal.addReport("test report 2", new File("c:/temp/report-1.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_Reports' [JOURNAL_ID, BIGINT(19), NO, , NULL] [DESCRIPTION, VARCHAR(255), YES, , NULL] [FILE, VARCHAR(255), YES, , NULL] Persisting journal: Journal{id=0, reports=[Report{, description='test report 1', file=c:\temp\report-1.txt}, Report{, description='test report 2', file=c:\temp\report-1.txt}]} 'Select * from Journal' 1 'Select * from Journal_Reports' [1, test report 1, c:\temp\report-1.txt] [1, test report 2, c:\temp\report-1.txt] Journal loaded: Journal{id=1, reports=[Report{, description='test report 1', file=c:\temp\report-1.txt}, Report{, description='test report 2', file=c:\temp\report-1.txt}]}
In above example, if we don't use @Convert on the collection attribute then File instance will be persisted as a binary form. All Serializable types which are not Java Basic types (String, primitives etc) can be persisted into VARBINARY SQL type, check out this tutorial for details.
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
|
|