<dependency> <groupId>javax.persistence</groupId> <artifactId>javax.persistence-api</artifactId> <version>2.2</version> </dependency>
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.7.0 </version> </dependency>
java.time.LocalDate
java.time.LocalTime
java.time.LocalDateTime
java.time.OffsetTime
java.time.OffsetDateTime
java.util.Date
and java.sql.Timestamp
. Therefore, you need to use the converter to convert the date stored in the database into the old design, which is supported by the JPA 2.1 version, and then convert to the updated Date and Time API for use in the application. The date converter to JPA 2.1, capable of such a conversion, may look something like the one shown in Listing 1. The converter in it is used to convert between LocalDate
and java.util.Date
. @Converter(autoApply = true) public class LocalDateTimeConverter implements AttributeConverter<LocalDate, Date> { @Override public Date convertToDatabaseColumn(LocalDate entityValue) { LocalTime time = LocalTime.now(); Instant instant = time.atDate(entityValue) .atZone(ZoneId.systemDefault()) .toInstant(); return Date.from(instant); } @Override public LocalDate convertToEntityAttribute(Date databaseValue){ Instant instant = Instant.ofEpochMilli(databaseValue.getTime()); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalDate(); } }
@Temporal
code, because type mapping happens automatically. public class Job implements Serializable { . . . @Column(name = "WORK_DATE") private LocalDate workDate; . . . }
@Temporal
annotation should be described in all permanent fields and properties such as java.util.Date
and java.util.Calendar
.LocalDateTime
to ZonedDateTime
. The biggest problem in writing such a converter is to determine how best to convert between different types. To make things even easier, attribute converters can now be implemented. I will give an example implementation below.LocalDateTime
to ZonedDateTime
. @Converter public class LocalToZonedConverter implements AttributeConverter<ZonedDateTime, LocalDateTime> { @Override public LocalDateTime convertToDatabaseColumn(ZonedDateTime entityValue) { return entityValue.toLocalDateTime(); } @Override public ZonedDateTime convertToEntityAttribute(LocalDateTime databaseValue) { return ZonedDateTime.of(databaseValue, ZoneId.systemDefault()); } }
ZonedDateTime
contains methods that are easy to convert. The conversion is done by calling the toLocalDateTime()
method. The inverse transform can be performed by calling the ZonedDateTimeOf()
method and passing the LocalDateTime
value along with ZoneId
for use by the time zone.javax.persistence.AttributeConverter
interface by passing X and Y values. The X value corresponds to the data type in the Java object, and the Y value must match the column type of the database. Then, the converter class should be annotated with @Converter
. Finally, the class must override the convertToDatabaseColumn()
and convertToEntityAttribute()
methods. An implementation in each of these methods should convert values from certain types and back to them.@Converter(autoApply=true)
. To apply a converter to a single attribute, use the @Converter annotation at the attribute level, as shown here: @Convert(converter=LocalDateConverter.java) private LocalDate workDate;
@Convert(attributeName="workDate", converter = LocalDateConverter.class) public class Job implements Serializable { . . .
creditLimit
field of the Customer
entity when it is saved. To implement such a process, the values must be encrypted before being saved and decrypted after being extracted from the database. This can be done with a converter and, using JPA 2.2, I can embed an encryption object in the converter to achieve the desired result. Listing 3 is an example. @Converter public class CreditLimitConverter implements AttributeConverter<BigDecimal, BigDecimal> { @Inject CreditLimitEncryptor encryptor; @Override public BigDecimal convertToDatabaseColumn (BigDecimal entityValue) { String encryptedFormat = encryptor.base64encode(entityValue.toString()); return BigDecimal.valueOf(Long.valueOf(encryptedFormat)); } ... }
CreditLimitEncryptor
class in the converter and its subsequent use to assist the process.ResultSet
pagination may work better than streams.getResultStream()
method was added to the Query
and TypedQuery
. This minor change allows JPA to simply return a result stream instead of a list. Thus, if you are working with a large ResultSet
, it makes sense to compare the performance between the new implementation of the threads and the scrollable ResultSets
or pagination. The reason is that the implementations of the threads extract all the records at the same time, save them to the list and then return. Scrollable ResultSet
and pagination techniques extract data in parts, which may be better for large data sets.getResultStream()
method getResultStream()
improved implementation. Hibernate already includes a stream () method that uses a scrollable ResultSet
to parse the results of records instead of returning them completely. This allows Hibernate to work with very large data sets and to do it well. Other providers can be expected to override this method to provide similar features that benefit JPA.Job
entity and return the stream. First, let's take a look at the following code, where I simply analyze the stream of Jobs
for a specific Customer
, calling the Query
getResultStream()
interface method. Then, I use this stream to output the details regarding the customer
and work date
Job'a. public void findByCustomer(PoolCustomer customer){ Stream<Job> jobList = em.createQuery("select object(o) from Job o " + "where o.customer = :customer") .setParameter("customer", customer) .getResultStream(); jobList.map(j -> j.getCustomerId() + " ordered job " + j.getId() + " - Starting " + j.getWorkDate()) .forEach(jm -> System.out.println(jm)); }
Collectors .toList()
method as follows. public List<Job> findByCustomer(PoolCustomer customer){ Stream<Job> jobList = em.createQuery( "select object(o) from Job o " + "where o.customerId = :customer") .setParameter("customer", customer) .getResultStream(); return jobList.collect(Collectors.toList()); }
List
tasks related to pools of a particular form. In this case, I return all tasks that match the form submitted as a string. Similar to the first example, first I return a stream of Jobs
records. Then, I filter the records based on the form of the customer pool. As you can see, the resulting code is very compact and easy to read. public List<Job> findByCustPoolShape(String poolShape){ Stream<Job> jobstream = em.createQuery( "select object(o) from Job o") .getResultStream(); return jobstream.filter( c -> poolShape.equals(c.getCustomerId().getPoolId().getShape())) .collect(Collectors.toList()); }
@SqlResultSetMapping
annotation for a given entity class. In such situations, when re-annotation support is required, container annotation should be used. Repeated annotations not only reduce the requirement to wrap collections of identical annotations in a container annotation, but can also make the code easier to read.@Repeatable
meta-annotation to indicate that it can be used more than once. The @Repeatable
meta annotation accepts a container annotation class type. For example, the NamedQuery
annotation NamedQuery
now marked with an @Repeatable(NamedQueries.class)
annotation. In this case, the container annotation is still used, but you don’t have to think about it when using the same annotation on the declaration or class, because @Repeatable
abstracts this part.@NamedQuery
annotation to an entity class in JPA 2.1, you need to encapsulate them inside the @NamedQueries
annotation, as shown in Listing 4. @Entity @Table(name = "CUSTOMER") @XmlRootElement @NamedQueries({ @NamedQuery(name = "Customer.findAll", query = "SELECT c FROM Customer c") , @NamedQuery(name = "Customer.findByCustomerId", query = "SELECT c FROM Customer c " + "WHERE c.customerId = :customerId") , @NamedQuery(name = "Customer.findByName", query = "SELECT c FROM Customer c " + "WHERE c.name = :name") . . .)}) public class Customer implements Serializable { . . . }
@NamedQuery
is a repeating annotation, it may appear in the entity class more than once, as shown in Listing 5. @Entity @Table(name = "CUSTOMER") @XmlRootElement @NamedQuery(name = "Customer.findAll", query = "SELECT c FROM Customer c") @NamedQuery(name = "Customer.findByCustomerId", query = "SELECT c FROM Customer c " + "WHERE c.customerId = :customerId") @NamedQuery(name = "Customer.findByName", query = "SELECT c FROM Customer c " + "WHERE c.name = :name") . . . public class Customer implements Serializable { . . . }
@AssociationOverride
@AttributeOverride
@Convert
@JoinColumn
@MapKeyJoinColumn
@NamedEntityGraphy
@NamedNativeQuery
@NamedQuery
@NamedStoredProcedureQuery
@PersistenceContext
@PersistenceUnit
@PrimaryKeyJoinColumn
@SecondaryTable
@SqlResultSetMapping
Source: https://habr.com/ru/post/423195/
All Articles