JPA: Difference between revisions

From Chorke Wiki
Jump to navigation Jump to search
 
(32 intermediate revisions by the same user not shown)
Line 6: Line 6:


The Instant class represents a moment on the timeline in '''UTC''' with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).All three java.time.Local… classes are all lacking any concept of time zone or offset-from-UTC.
The Instant class represents a moment on the timeline in '''UTC''' with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).All three java.time.Local… classes are all lacking any concept of time zone or offset-from-UTC.
==Sequence Style==
<source lang="java">
@Id
@Column(name = "code", length = 6)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "page_sqn")
//@SequenceGenerator(name = "page_sqn", sequenceName = "page_sqn", initialValue = 60466176, allocationSize = 1)
@GenericGenerator(name  = "page_sqn", strategy = "org.chorke.academia.core.entity.Base36Style", parameters = {
    @Parameter(name = Base36Style.INITIAL_VALUE,  value = Base36Style.DIGIT_6_MIN),
    @Parameter(name = Base36Style.SEQUENCE_NAME,  value = "page_sqn"),
    @Parameter(name = Base36Style.ALLOCATION_SIZE, value = "1"),
})
private String code;
</source>
<source lang="java" highlight="15-17,34,41">
package org.chorke.academia.core.entity;
import java.io.Serializable;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;
public class Base36Style extends SequenceStyleGenerator {
    private static final Logger LOG = LoggerFactory.getLogger(Base36Style.class);
    public static final String ALLOCATION_SIZE = INCREMENT_PARAM;
    public static final String SEQUENCE_NAME  = SEQUENCE_PARAM;
    public static final String INITIAL_VALUE  = INITIAL_PARAM;
    public static final int    RADIX = 36;
    public static final String DIGIT_1_MIN = "0";              //            0 =>            Z
    public static final String DIGIT_2_MIN = "36";              //          10 =>            ZZ
    public static final String DIGIT_3_MIN = "1296";            //          100 =>          ZZZ
    public static final String DIGIT_4_MIN = "46656";          //        1,000 =>        Z,ZZZ
    public static final String DIGIT_5_MIN = "1679616";        //      10,000 =>        ZZ,ZZZ
    public static final String DIGIT_6_MIN = "60466176";        //      100,000 =>      ZZZ,ZZZ
    public static final String DIGIT_7_MIN = "2176782336";      //    1,000,000 =>    Z,ZZZ,ZZZ
    public static final String DIGIT_8_MIN = "78364164096";    //  10,000,000 =>    ZZ,ZZZ,ZZZ
    public static final String DIGIT_9_MIN = "2821109907456";  //  100,000,000 =>  ZZZ,ZZZ,ZZZ
    public static final String DIGIT_X_MIN = "101559956668416"; //1,000,000,000 => Z,ZZZ,ZZZ,ZZZ
    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        Serializable nextval = super.generate(session, object);
        String base36 = Long.toString((Long) nextval, RADIX);
        LOG.debug("Base36: {}", base36.toUpperCase());
        return base36.toUpperCase();
    }
    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
        super.configure(LongType.INSTANCE, params, serviceRegistry);
    }
}
</source>


==Challenges==
==Challenges==
Line 11: Line 71:
|-
|-
! Database !! Auto Increment !! Sequence !! Usable
! Database !! Auto Increment !! Sequence !! Usable
|-
! DB2/LUW
| <code>✓</code> || <code>✓</code> || <code>✓</code>
|-
! DB2/z
| <code>✓</code> || <code>✓</code> || <code>✓</code>
|-
! PostgreSQL
| <code>✓</code> || <code>✓</code> || <code>✓</code>
|-
|-
! Derby
! Derby
Line 17: Line 86:
! Firebird
! Firebird
| <code>✕</code> || <code>✓</code> || <code>✓</code>
| <code>✕</code> || <code>✓</code> || <code>✓</code>
|-
! H2
| <code>✓</code> || <code>✓</code> || <code>✓</code>
|-
! HyperSQL
| <code>✓</code> || <code>✓</code> || <code>✓</code>
|-
|-
! INGRES
! INGRES
| <code>✓</code> || <code>✕</code> || <code>✕</code>
| <code>✓</code> || <code>✕</code> || <code>✕</code>
|-
! Informix
| <code>✓</code> || <code>✓</code> || <code>✓</code>
|-
|-
! MariaDB
! MariaDB
Line 38: Line 116:
! Sybase
! Sybase
| <code>✓</code> || <code>✕</code> || <code>✕</code>
| <code>✓</code> || <code>✕</code> || <code>✕</code>
|-
! Sybase Anywhere
| <code>✓</code> || <code>✓</code> || <code>✓</code>
|}
==Date Time==
<source lang="java">
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
class Playground {
    public static void main(String[ ] args) {
        System.out.println("Yesterday Min: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusDays(1L));
        System.out.println("Yesterday Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusNanos(1L));
        System.out.println("Yesterday Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusDays(1L).plusDays(1L).minusNanos(1L));
        System.out.println("Yesterday Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusDays(1L).plusHours(24).minusNanos(1L));
        System.out.println();
        System.out.println("Today    Min: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS));
        System.out.println("Today    Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusDays(1L).minusNanos(1L));
        System.out.println("Today    Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusHours(24).minusNanos(1L));
        System.out.println();
        System.out.println("Tomorrow Min: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusDays(1L));
        System.out.println("Tomorrow Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusDays(2L).minusNanos(1L));
        System.out.println("Tomorrow Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusHours(48).minusNanos(1L));
    }
}
</source>
==Knowledge==
{|
| valign="top" colspan="2" |
<source lang='java'>
import org.hibernate.Session;
Session session = (Session) entityManager.getDelegate();
Page<Country> countries = countryRepo.findAll(page);
countries = countries.map(country -> {
    session.evict(country);
    if (ObjectUtils.isEmpty(country.getContinent())) {
        Continent continent = continentRepo.findById(country.getContinentCode());
        country.setContinent(continent);
        return country;
    } else return country;
});
</source>
|-
| colspan="2" |
----
|-
| valign="top" colspan="2" |
<source lang='java'>
@PersistenceContext
EntityManager entityManager;
if (entityManager.contains(country)) entityManager.detach(country);
//  entityManager.detach(country);
</source>
|-
| colspan="2" |
----
|-
| valign="top" |
| valign="top" |
|}
|}


Line 67: Line 214:


| valign="top" |
| valign="top" |
* [https://stackoverflow.com/questions/21708339/ Prevent Jackson to Serialize <code>Non-Fetched Lazy</code> Objects]
* [https://stackoverflow.com/questions/57168773/ Does JPA delete also remove large objects of Blob fields]
* [https://programmer.group/oracle-to-mysql-database-migration-primary-key-generation-policy-replacement.html Using MySQL table to simulate Oracle Sequence]
* [https://www.baeldung.com/spring-data-jpa-stored-procedures Calling Stored Procedures from Spring Data JPA]
* [https://stackoverflow.com/questions/28539915/ Multiple SequenceGenerator in Hibernate Entity]
* [https://coderanch.com/t/573996/databases/SequenceGenerator-MySql-Database <code>@SequenceGenerator</code> for MySql Database]
* [https://docs.liquibase.com/change-types/community/create-sequence.html#:~:text=Database%20support Create Sequence Supported Database]
* [https://docs.liquibase.com/change-types/community/create-sequence.html#:~:text=Database%20support Create Sequence Supported Database]
* [https://vladmihalcea.com/ Vlad Mihalcea the Java Champion]
* [https://github.com/eugenp/tutorials/blob/master/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java Example of Stored Procedure]
* [[Liquibase]]
|-
| colspan="3" |
----
|-
| valign="top" |
* [https://stackoverflow.com/questions/45973070/ Spring JPA ExampleMatcher compare date condition]
* [https://stackoverflow.com/questions/60112439 Difference btn. <code>evict</code> and <code>detach</code> in hibernate]
* [https://stackoverflow.com/questions/65478350/ Column type is JSON but expression is Varchar]
* [https://stackoverflow.com/questions/39620317/ Map a JSON column with H2 & Spring JPA]
* [https://stackoverflow.com/questions/2311125/ Ignore Hibernate <code>@Where</code> annotation]
* [https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html Java » ISO <code>DateTimeFormatter</code>]
* [https://stackoverflow.com/questions/7700071/  Use  <code>@Where</code> in Hibernate]
* [[PostgreSQL]]
* [[MapStruct]]
* [[Lombok]]


|}
|}

Latest revision as of 18:06, 1 February 2024

Replacements

java.util.Date     => java.time.Instant
java.sql.Timestamp => java.time.Instant
java.sql.Date      => java.time.LocalDate
java.sql.Time      => java.time.LocalTime

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).All three java.time.Local… classes are all lacking any concept of time zone or offset-from-UTC.

Sequence Style

@Id
@Column(name = "code", length = 6)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "page_sqn")
//@SequenceGenerator(name = "page_sqn", sequenceName = "page_sqn", initialValue = 60466176, allocationSize = 1)
@GenericGenerator(name  = "page_sqn", strategy = "org.chorke.academia.core.entity.Base36Style", parameters = {
    @Parameter(name = Base36Style.INITIAL_VALUE,   value = Base36Style.DIGIT_6_MIN),
    @Parameter(name = Base36Style.SEQUENCE_NAME,   value = "page_sqn"),
    @Parameter(name = Base36Style.ALLOCATION_SIZE, value = "1"),
})
private String code;
package org.chorke.academia.core.entity;

import java.io.Serializable;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;

public class Base36Style extends SequenceStyleGenerator {
    private static final Logger LOG = LoggerFactory.getLogger(Base36Style.class);
    public static final String ALLOCATION_SIZE = INCREMENT_PARAM;
    public static final String SEQUENCE_NAME   = SEQUENCE_PARAM;
    public static final String INITIAL_VALUE   = INITIAL_PARAM;
    public static final int    RADIX = 36;

    public static final String DIGIT_1_MIN = "0";               //            0 =>             Z
    public static final String DIGIT_2_MIN = "36";              //           10 =>            ZZ
    public static final String DIGIT_3_MIN = "1296";            //          100 =>           ZZZ
    public static final String DIGIT_4_MIN = "46656";           //        1,000 =>         Z,ZZZ
    public static final String DIGIT_5_MIN = "1679616";         //       10,000 =>        ZZ,ZZZ
    public static final String DIGIT_6_MIN = "60466176";        //      100,000 =>       ZZZ,ZZZ
    public static final String DIGIT_7_MIN = "2176782336";      //    1,000,000 =>     Z,ZZZ,ZZZ
    public static final String DIGIT_8_MIN = "78364164096";     //   10,000,000 =>    ZZ,ZZZ,ZZZ
    public static final String DIGIT_9_MIN = "2821109907456";   //  100,000,000 =>   ZZZ,ZZZ,ZZZ
    public static final String DIGIT_X_MIN = "101559956668416"; //1,000,000,000 => Z,ZZZ,ZZZ,ZZZ

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        Serializable nextval = super.generate(session, object);
        String base36 = Long.toString((Long) nextval, RADIX);
        LOG.debug("Base36: {}", base36.toUpperCase());
        return base36.toUpperCase();
    }

    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
        super.configure(LongType.INSTANCE, params, serviceRegistry);
    }
}

Challenges

Database Auto Increment Sequence Usable
DB2/LUW
DB2/z
PostgreSQL
Derby
Firebird
H2
HyperSQL
INGRES
Informix
MariaDB
MySQL
Oracle
Sql Server
SQLite
Sybase
Sybase Anywhere

Date Time

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

class Playground {
    public static void main(String[ ] args) {
        System.out.println("Yesterday Min: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusDays(1L));
        System.out.println("Yesterday Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusNanos(1L));
        System.out.println("Yesterday Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusDays(1L).plusDays(1L).minusNanos(1L));
        System.out.println("Yesterday Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusDays(1L).plusHours(24).minusNanos(1L));

        System.out.println();
        System.out.println("Today    Min: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS));
        System.out.println("Today    Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusDays(1L).minusNanos(1L));
        System.out.println("Today    Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusHours(24).minusNanos(1L));

        System.out.println();
        System.out.println("Tomorrow Min: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusDays(1L));
        System.out.println("Tomorrow Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusDays(2L).minusNanos(1L));
        System.out.println("Tomorrow Max: " + LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).plusHours(48).minusNanos(1L));
    }
}

Knowledge

import org.hibernate.Session;

Session session = (Session) entityManager.getDelegate();
Page<Country> countries = countryRepo.findAll(page);
countries = countries.map(country -> {
    session.evict(country);
    if (ObjectUtils.isEmpty(country.getContinent())) {
        Continent continent = continentRepo.findById(country.getContinentCode());
        country.setContinent(continent);
        return country;
    } else return country;
});

@PersistenceContext
EntityManager entityManager;

if (entityManager.contains(country)) entityManager.detach(country);
//  entityManager.detach(country);

References