Frapp:ee Documentation

Frapp:ee is a collection of ORM solutions. Its structure is modular, and almost everything can be overridden at the project level. The framework is based on coffee-ee modules.

1. frappee-jpa

Collection of JPA specific solutions.

1.1. frappee-jpa-batch-api

Tha API of JPA specific batch services:

  • hu.icellmobilsoft.frappee.jpa.batch.IJpaBatchService

2. frappee-hibernate

The purpose of this module is to provide Hibernate specific services.

Can be used from Wildfly 30.0.1.Final because it already contains Hibernate 6.2.13.Final.

2.1. frappee-hibernate-batch

The Hibernate specific implementation of the frappee-jpa-batch-api module.

2.2. HibernateBatchService

The HibernateBatchService is a Hibernate specific implementation of the hu.icellmobilsoft.frappee.jpa.batch.IJpaBatchService interface. It is used to perform bulk database operations (insert, update, delete) in a group.
It mainly contains batch operations based on PreparedStatement, in which SQL compilation is performed with the support of Hibernate.

Type support

HibernateBatchService supports operations on the following types with certainty:

Support type Java types

Null treated as value

All types evaluated as null by hibernate.

CustomType treated as type

Currently, there is no specific type, it is used due to the possibility of extending

Enum treated as type

All enum types.

ManyToOneType treated as type

All types annotated with @ManyToOne.

ConvertedBasicType treated as type

All types with a converter.

BasicType treated as a type

boolean, Boolean

char, Character

java.sql.Date, java.sql.Time, java.sql.Timestamp

java.util.Date, java.util.Calendar

LocalDate, LocalTime, LocalDateTime, OffsetTime, OffsetDateTime, ZonedDateTime, Instant

Blob, byte[], Byte[]

Managed by JDBC driver

byte, short, int, long, float, double

byte, short, integer, long, float, double

BigInteger, BigDecimal

String

All other types not in the list.

For special types it is recommended to use a custom converter.
Types not listed here are handled by the specific JDBC driver.
Type support has been tested on postgresql and oracle databases to ensure correct operation. For all other databases, type coverage is in theory mostly guaranteed, but anomalies may occur.
Null value handling

HibernateBatchService starts type handling with a null scan. If the value of any type returned by hibernate is null, HibernateBatchService sets the value as SqlTypes.NULL JDBC type using the PreparedStatement.setNull() method.

JDBC drivers also use this method.
CustomType handling

HibernateBatchService currently does not handle any CustomType directly, but it provides the possibility to extend it. By default, all CustomType types are handled by the JDBC driver used!

Enum types handling

HibernateBatchService handles the resolution of Enum types as follows:

Java code value inserted by HibernateBatchService
@Column(name = "ENUM_DEFAULT")
private EnumType enumDefault;

The order associated with the given enum value, the value is inserted according to the ordinal() method.

@Column(name = "ENUM_ORDINAL")
@Enumerated(value = EnumType.ORDINAL)
private EnumType enumOrdinal;

The order associated with the given enum value, the value is inserted according to the ordinal() method.

@Column(name = "ENUM_STRING")
@Enumerated(value = EnumType.STRING)
private EnumType enumString;

The name associated with the given non-value, the value is inserted according to the name() method.

ManyToOneType handling

Within an entity, fields that use the @ManyToOne (jakarta.persistence.ManyToOne) annotation are treated by hibernate as ManyToOneType.
These ManyToOneType types are handled by HibernateBatchService as follows:

Java code value inserted by HibernateBatchService
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MANY_TO_ONE_SAMPLE_ENTITY")
private SampleEntity manyToOneSampleEntity;

The HibernateBatchService takes the unique identifier of the given entity and injects it using EntityHelper.getLazyId().

ConvertedBasicType handling

Fields within an entity that have a converter, i.e. have the @Convert (jakarta.persistence.Convert) annotation placed on them, are treated by hibernate as ConvertedBasicType.

For example:
@Convert(converter = YearMonthAttributeConverter.class)
@Column(name = "YEAR_MONTH")
private YearMonth yearMonth;

For this type, Hibernate contains the JDBC type and all additional settings for the converted value, but the conversion must be done manually. Thus, the HibernateBatchService calls the passed converter, and then passes it on to the BasicType management process with the value obtained during the conversion and the ConvertedBasicType (BasicType) type set appropriately by hibernate.

BasicType handling

The BasicType type combines the java and jdbc types, so for each java type it contains the corresponding jdbc type. The separations are thus done according to the jdbc type code stored in the jdbc type.

Date type BasicType handling

SqlTypes.DATE BasicType types with a jdbc type code SqlTypes.DATE are handled by HibernateBatchService as follows:

Java code value inserted by HibernateBatchService
@Column(name = "DATE")
private java.sql.Date date;

Can be set directly, without conversion, using the PreparedStatement.setDate() method.

@Column(name = "LOCAL_DATE")
private LocalDate localDate;

Converted to java.sql.Date type, then set using PreparedStatement.setDate() method.

@Temporal(TemporalType.DATE)
@Column(name = "DATE_TEMPORAL_DATE")
private java.util.Date dateTemporalDate;

Converted to java.sql.Date type, then set using PreparedStatement.setDate() method.

@Temporal(TemporalType.DATE)
@Column(name = "CALENDAR_TEMPORAL_DATE")
private Calendar calendarTemporalDate;

Converted to java.sql.Date type, then set using PreparedStatement.setDate() method.

Types not in the table are set by the JDBC driver.
Time type BasicType handling

The SqlTypes.TIME and SqlTypes.TIME_WITH_TIMEZONE jdbc type code BasicType types are handled by HibernateBatchService as follows:

Java code value inserted by HibernateBatchService
@Column(name = "TIME")
private Time time;

Can be set directly, without conversion, using the PreparedStatement.setTime() method.

@Column(name = "LOCAL_TIME")
private LocalTime localTime;

Converted to java.sql.Time type, then set using PreparedStatement.setTime() method.

@Column(name = "OFFSET_TIME")
private OffsetTime offsetTime;

The system returned by ZoneId.systemDefault() is converted to a time zone, then converted to java.sql.Time and set using the PreparedStatement.setTime() method.

@Temporal(TemporalType.TIME)
@Column(name = "DATE_TEMPORAL_TIME")
private java.util.Date dateTemporalTime;

Converted to java.sql.Time type, then set using PreparedStatement.setTime() method.

@Temporal(TemporalType.TIME)
@Column(name = "CALENDAR_TEMPORAL_TIME")
private Calendar calendarTemporalTime;

Converted to java.sql.Time type, then set using PreparedStatement.setTime() method.

For the types listed in the table, if hibernate.jdbc.time_zone is set in persistence.xml, then the time zone is also passed to the PreparedStatement.setTime() method, so that the JDBC driver can perform the appropriate time offset according to the time zone.

It is up to the JDBC driver to set the types not listed in the table.
Timestamp type BasicType handling

The SqlTypes.TIMESTAMP, SqlTypes.TIMESTAMP_UTC and SqlTypes.TIMESTAMP_WITH_TIMEZONE jdbc type code BasicType types are handled by HibernateBatchService as follows:

Java code value inserted by HibernateBatchService
@Column(name = "TIMESTAMP_DEFAULT")
private Timestamp timestampDefault;

Can be set directly, without conversion, using the PreparedStatement.setTimestamp() method.

@Column(name = "LOCAL_DATE_TIME")
private LocalDateTime localDateTime;

Converted to java.sql.Timestamp type, then set using PreparedStatement.setTimestamp() method.

@Column(name = "OFFSET_DATE_TIME")
private OffsetDateTime offsetDateTime;

The system returned by ZoneId.systemDefault() is converted to a time zone, then converted to java.sql.Timestamp type, and set using PreparedStatement.setTimestamp() method.

@Column(name = "ZONED_DATE_TIME")
private ZonedDateTime zonedDateTime;

The system returned by ZoneId.systemDefault() is converted to a time zone, then converted to java.sql.Timestamp type and set using PreparedStatement.setTimestamp() method.

@Column(name = "INSTANT")
private Instant instant;

The system time zone returned by ZoneId.systemDefault() is converted to java.sql.Timestamp and then set using PreparedStatement.setTimestamp().

@Column(name = "DATE_DEFAULT")
private java.util.Date dateDefault;

Converted to java.sql.Timestamp type, then set using PreparedStatement.setTimestamp() method.

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "DATE_TEMPORAL_TS")
private java.util.Date dateTemporalTS;

Converted to java.sql.Timestamp type, then set using PreparedStatement.setTimestamp() method.

@Column(name = "CALENDAR_DEFAULT")
private Calendar calendarDefault;

Converted to java.sql.Timestamp type, then set using PreparedStatement.setTimestamp() method.

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CALENDAR_TEMPORAL_TS")
private Calendar calendarTemporalTS;

Converted to java.sql.Timestamp type, then set using PreparedStatement.setTimestamp() method.

For the types listed in the table, if hibernate.jdbc.time_zone is set in persistence.xml, then the time zone is also passed to the PreparedStatement.setTimestamp() method, so that the JDBC driver can perform the appropriate time offset according to the time zone.

It is up to the JDBC driver to set the types not listed in the table.
Boolean type BasicType handling

BasicType types with SqlTypes.BOOLEAN jdbc type code are handled by HibernateBatchService as follows:

Java code value inserted by HibernateBatchService
@Column(name = "BOOLEAN_PRIMITIVE")
private boolean booleanPrimitive;

Can be set directly, without conversion, using the PreparedStatement.setBoolean() method.

@Column(name = "BOOLEAN_WRAPPER")
private Boolean booleanWrapper;

Can be set directly, without transformation, using the PreparedStatement.setBoolean() method.

For types not listed in the table, it is up to the JDBC driver to set them.
Char type BasicType handling

BasicType types with SqlTypes.BOOLEAN jdbc type code are handled by HibernateBatchService as follows:

Java Code value inserted by HibernateBatchService
@Column(name = "CHAR_PRIMITIVE")
private char charPrimitive;

Converted to String type, then set using PreparedStatement.setString() method.

@Column(name = "CHAR_WRAPPER")
private Character charWrapper;

Converted to String type, then set using PreparedStatement.setString() method.

Types not listed in the table are set by the JDBC driver.
Data type BasicType handling

The SqlTypes.BLOB, SqlTypes.VARBINARY and SqlTypes.LONGVARBINARY jdbc type code BasicType types are handled by HibernateBatchService as follows:

Java code value inserted by HibernateBatchService
@Lob
@Column(name = "DEFAULT_BLOB")
private Blob defaultBlob;

Converted to InputStream type, then set using PreparedStatement.setBinaryStream() method.

@Column(name = "PRIMITIVE_BYTE_ARRAY")
private byte[] primitiveByteArray;

Can be set directly, without conversion, using the PreparedStatement.setBytes() method.

@Column(name = "WRAPPER_BYTE_ARRAY")
private Byte[] wrapperByteArray;

If the legacy array handling is enabled:

  • Converted to primitive byte[] type, then set using PreparedStatement.setBytes() method.

If the legacy array handling is not enabled:

  • We let it be handled by the used JDBC driver.

If possible, it is recommended to use byte[] instead.
@Lob
@Column(name = "LOB_PRIMITIVE_BYTE_ARRAY")
private byte[] lobPrimitiveByteArray;

Can be set directly, without conversion, using the PreparedStatement.setBytes() method.

@Lob
@Column(name = "LOB_WRAPPER_BYTE_ARRAY")
private Byte[] lobWrapperByteArray;

If the legacy array handling is enabled:

  • Converted to primitive byte[] type, then set using PreparedStatement.setBytes() method.

If the legacy array handling is not enabled:

  • We let it be handled by the used JDBC driver.

If possible, it is recommended to use byte[] instead.
The JDBC driver is responsible for setting types not included in the table.
To enable legacy array handling, persistence.xml needs to be extended with the following property: <property name="hibernate.type.wrapper_array_handling" value="legacy"/>. See more: hibernate 6.2 migration guide

Migration descriptions