2020-06-30

Spring boot : Application Events and Listeners - ApplicationContextInitializedEvent

Spring boot : Application Events and Listeners - ApplicationContextInitializedEvent

ApplicationContextInitializedEvent


An ApplicationContextInitializedEvent is sent when the ApplicationContext is prepared and ApplicationContextInitializers have been called but before any bean definitions are loaded.

Spring boot : Application Events and Listeners - ApplicationEnvironmentPreparedEvent

Spring boot : Application Events and Listeners - ApplicationEnvironmentPreparedEvent

ApplicationEnvironmentPreparedEvent 


An ApplicationEnvironmentPreparedEvent is sent when the Environment to be used in the context is known but before the context is created.

Spring boot : Application Events and Listeners - ApplicationStartingEvent

Spring boot : Application Events and Listeners - ApplicationStartingEvent

ApplicationStartingEvent 


An ApplicationStartingEvent is sent at the start of a run but before any processing, except for the registration of listeners and initializers.

Spring boot Liveness State vs Readiness State

Application Availability

When deployed on platforms, applications can provide information about their availability to the platform using infrastructure such as Kubernetes Probes. Spring Boot includes out-of-the box support for the commonly used “liveness” and “readiness” availability states. If you are using Spring Boot’s “actuator” support then these states are exposed as health endpoint groups.

In addition, you can also obtain availability states by injecting the ApplicationAvailability interface into your own beans.

Liveness State

The “Liveness” state of an application tells whether its internal state allows it to work correctly, or recover by itself if it’s currently failing. A broken “Liveness” state means that the application is in a state that it cannot recover from, and the infrastructure should restart the application.

In general, the "Liveness" state should not be based on external checks, such as Health checks. If it did, a failing external system (a database, a Web API, an external cache) would trigger massive restarts and cascading failures across the platform.
The internal state of Spring Boot applications is mostly represented by the Spring ApplicationContext. If the application context has started successfully, Spring Boot assumes that the application is in a valid state. An application is considered live as soon as the context has been refreshed, see Spring Boot application lifecycle and related Application Events.

Readiness State

The “Readiness” state of an application tells whether the application is ready to handle traffic. A failing “Readiness” state tells the platform that it should not route traffic to the application for now. This typically happens during startup, while CommandLineRunner and ApplicationRunner components are being processed, or at any time if the application decides that it’s too busy for additional traffic.

An application is considered ready as soon as application and command-line runners have been called, see Spring Boot application lifecycle and related Application Events.

Tasks expected to run during startup should be executed by CommandLineRunner and ApplicationRunner components instead of using Spring component lifecycle callbacks such as @PostConstruct.

Managing the Application Availability State

Application components can retrieve the current availability state at any time, by injecting the ApplicationAvailability interface and calling methods on it. More often, applications will want to listen to state updates or update the state of the application.

For example, we can export the "Readiness" state of the application to a file so that a Kubernetes "exec Probe" can look at this file:

@Component
public class ReadinessStateExporter {

    @EventListener
    public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
        switch (event.getState()) {
        case ACCEPTING_TRAFFIC:
            // create file /tmp/healthy
        break;
        case REFUSING_TRAFFIC:
            // remove file /tmp/healthy
        break;
        }
    }

}
We can also update the state of the application, when the application breaks and cannot recover:

@Component
public class LocalCacheVerifier {

    private final ApplicationEventPublisher eventPublisher;

    public LocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void checkLocalCache() {
        try {
            //...
        }
        catch (CacheCompletelyBrokenException ex) {
            AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
        }
    }

}

What is Springboot Lazy Initialization?

SpringApplication allows an application to be initialized lazily. When lazy initialization is enabled, beans are created as they are needed rather than during application startup. As a result, enabling lazy initialization can reduce the time that it takes your application to start. In a web application, enabling lazy initialization will result in many web-related beans not being initialized until an HTTP request is received.

A downside of lazy initialization is that it can delay the discovery of a problem with the application. If a misconfigured bean is initialized lazily, a failure will no longer occur during startup and the problem will only become apparent when the bean is initialized. Care must also be taken to ensure that the JVM has sufficient memory to accommodate all of the application’s beans and not just those that are initialized during startup. For these reasons, lazy initialization is not enabled by default and it is recommended that fine-tuning of the JVM’s heap size is done before enabling lazy initialization.

Lazy initialization can be enabled programmatically using the lazyInitialization method on SpringApplicationBuilder or the setLazyInitialization method on SpringApplication. Alternatively, it can be enabled using the spring.main.lazy-initialization property as shown in the following example:

spring.main.lazy-initialization=true

2020-06-28

Angular 10 : tabs/navigation Example

Angular 10 : tabs/navigation


Angular Material tabs organize content into separate views where only one view can be visible at a time. Each tab's label is shown in the tab header and the active tab's label is designated with the animated ink bar. When the list of tab labels exceeds the width of the header, pagination controls appear to let the user scroll left and right across the labels.

The active tab may be set using the selectedIndex input or when the user selects one of the tab labels in the header.

Events

The selectedTabChange output event is emitted when the active tab changes.

The focusChange output event is emitted when the user puts focus on any of the tab labels in the header, usually through keyboard navigation.


HTML:


<mat-tab-group mat-align-tabs="start">
  <mat-tab label="First">Content 1</mat-tab>
  <mat-tab label="Second">Content 2</mat-tab>
  <mat-tab label="Third">Content 3</mat-tab>
</mat-tab-group>

<mat-tab-group mat-align-tabs="center">
  <mat-tab label="First">Content 1</mat-tab>
  <mat-tab label="Second">Content 2</mat-tab>
  <mat-tab label="Third">Content 3</mat-tab>
</mat-tab-group>

<mat-tab-group mat-align-tabs="end">
  <mat-tab label="First">Content 1</mat-tab>
  <mat-tab label="Second">Content 2</mat-tab>
  <mat-tab label="Third">Content 3</mat-tab>
</mat-tab-group>


TS/JavaScript:


import {Component} from '@angular/core';

/**
 * @title Tab group with aligned labels
 */
@Component({
  selector: 'tab-group-align-example',
  templateUrl: 'tab-group-align-example.html',
  styleUrls: ['tab-group-align-example.css'],
})
export class TabGroupAlignExample {}

Angular 10 : autocomplete Example

Angular 10 : autocomplete


The autocomplete is a normal text input enhanced by a panel of suggested options.

Simple autocomplete

Start by creating the autocomplete panel and the options displayed inside it. Each option should be defined by a mat-option tag. Set each option's value property to whatever you'd like the value of the text input to be when that option is selected.

<mat-autocomplete #auto="matAutocomplete">
  <mat-option *ngFor="let option of options" [value]="option">
    {{option}}
  </mat-option>
</mat-autocomplete>

HTML:


<form class="example-form">
  <mat-form-field class="example-full-width">
    <input type="text"
           placeholder="Pick one"
           aria-label="Number"
           matInput
           [formControl]="myControl"
           [matAutocomplete]="auto">
    <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
      <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
        {{option}}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>

TS/JavaScript:


import {Component, OnInit} from '@angular/core';
import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators';

/**
 * @title Highlight the first autocomplete option
 */
@Component({
  selector: 'autocomplete-auto-active-first-option-example',
  templateUrl: 'autocomplete-auto-active-first-option-example.html',
  styleUrls: ['autocomplete-auto-active-first-option-example.css'],
})
export class AutocompleteAutoActiveFirstOptionExample implements OnInit {
  myControl = new FormControl();
  options: string[] = ['One', 'Two', 'Three'];
  filteredOptions: Observable<string[]>;

  ngOnInit() {
    this.filteredOptions = this.myControl.valueChanges.pipe(
      startWith(''),
      map(value => this._filter(value))
    );
  }

  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();

    return this.options.filter(option => option.toLowerCase().indexOf(filterValue) === 0);
  }
}

Angular 10 : checkbox example

Angular 10 : checkbox example


<mat-checkbox> provides the same functionality as a native <input type="checkbox"> enhanced with Material Design styling and animations.


HTML:


<mat-card>
  <mat-card-content>
    <h2 class="example-h2">Checkbox configuration</h2>

    <section class="example-section">
      <mat-checkbox class="example-margin" [(ngModel)]="checked">Checked</mat-checkbox>
      <mat-checkbox class="example-margin" [(ngModel)]="indeterminate">Indeterminate</mat-checkbox>
    </section>

    <section class="example-section">
      <label class="example-margin">Align:</label>
      <mat-radio-group [(ngModel)]="labelPosition">
        <mat-radio-button class="example-margin" value="after">After</mat-radio-button>
        <mat-radio-button class="example-margin" value="before">Before</mat-radio-button>
      </mat-radio-group>
    </section>

    <section class="example-section">
      <mat-checkbox class="example-margin" [(ngModel)]="disabled">Disabled</mat-checkbox>
    </section>
  </mat-card-content>
</mat-card>

<mat-card class="result">
  <mat-card-content>
    <h2 class="example-h2">Result</h2>

    <section class="example-section">
      <mat-checkbox
          class="example-margin"
          [(ngModel)]="checked"
          [(indeterminate)]="indeterminate"
          [labelPosition]="labelPosition"
          [disabled]="disabled">
        I'm a checkbox
      </mat-checkbox>
    </section>
  </mat-card-content>
</mat-card>


TS/JavaScript:


<mat-card>
  <mat-card-content>
    <h2 class="example-h2">Checkbox configuration</h2>

    <section class="example-section">
      <mat-checkbox class="example-margin" [(ngModel)]="checked">Checked</mat-checkbox>
      <mat-checkbox class="example-margin" [(ngModel)]="indeterminate">Indeterminate</mat-checkbox>
    </section>

    <section class="example-section">
      <label class="example-margin">Align:</label>
      <mat-radio-group [(ngModel)]="labelPosition">
        <mat-radio-button class="example-margin" value="after">After</mat-radio-button>
        <mat-radio-button class="example-margin" value="before">Before</mat-radio-button>
      </mat-radio-group>
    </section>

    <section class="example-section">
      <mat-checkbox class="example-margin" [(ngModel)]="disabled">Disabled</mat-checkbox>
    </section>
  </mat-card-content>
</mat-card>

<mat-card class="result">
  <mat-card-content>
    <h2 class="example-h2">Result</h2>

    <section class="example-section">
      <mat-checkbox
          class="example-margin"
          [(ngModel)]="checked"
          [(indeterminate)]="indeterminate"
          [labelPosition]="labelPosition"
          [disabled]="disabled">
        I'm a checkbox
      </mat-checkbox>
    </section>
  </mat-card-content>
</mat-card>


Angular 10 : input example

Angular 10 : input example


matInput is a directive that allows native <input> and <textarea> elements to work with <mat-form-field>.

<input> and <textarea> attributes

All of the attributes that can be used with normal <input> and <textarea> elements can be used on elements inside <mat-form-field> as well. This includes Angular directives such as ngModel and formControl.

The only limitation is that the type attribute can only be one of the values supported by matInput.

Supported <input> types

The following input types can be used with matInput:


  • color
  • date
  • datetime-local
  • email
  • month
  • number
  • password
  • search
  • tel
  • text
  • time
  • url
  • week

HTML:

<form class="example-form">
  <mat-form-field class="example-full-width">
    <mat-label>Email</mat-label>
    <input matInput [formControl]="emailFormControl" [errorStateMatcher]="matcher"
           placeholder="Ex. pat@example.com">
    <mat-hint>Errors appear instantly!</mat-hint>
    <mat-error *ngIf="emailFormControl.hasError('email') && !emailFormControl.hasError('required')">
      Please enter a valid email address
    </mat-error>
    <mat-error *ngIf="emailFormControl.hasError('required')">
      Email is <strong>required</strong>
    </mat-error>
  </mat-form-field>
</form>

TS/JavaScript:

import {Component} from '@angular/core';
import {FormControl, FormGroupDirective, NgForm, Validators} from '@angular/forms';
import {ErrorStateMatcher} from '@angular/material/core';

/** Error when invalid control is dirty, touched, or submitted. */
export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const isSubmitted = form && form.submitted;
    return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
  }
}

/** @title Input with a custom ErrorStateMatcher */
@Component({
  selector: 'input-error-state-matcher-example',
  templateUrl: './input-error-state-matcher-example.html',
  styleUrls: ['./input-error-state-matcher-example.css'],
})
export class InputErrorStateMatcherExample {
  emailFormControl = new FormControl('', [
    Validators.required,
    Validators.email,
  ]);

  matcher = new MyErrorStateMatcher();
}

Angular 10 : menu example

Angular 10 : menu example


<mat-menu> is a floating panel containing list of options.

By itself, the <mat-menu> element does not render anything. The menu is attached to and opened via application of the matMenuTriggerFor directive:

<button mat-button [matMenuTriggerFor]="menu">Menu</button>

HTML:


<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Example icon-button with a menu">
  <mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
  <button mat-menu-item>
    <mat-icon>dialpad</mat-icon>
    <span>Redial</span>
  </button>
  <button mat-menu-item disabled>
    <mat-icon>voicemail</mat-icon>
    <span>Check voice mail</span>
  </button>
  <button mat-menu-item>
    <mat-icon>notifications_off</mat-icon>
    <span>Disable alerts</span>
  </button>
</mat-menu>

TS/JavaScript:


import {Component} from '@angular/core';

/**
 * @title Menu with icons
 */
@Component({
  selector: 'menu-icons-example',
  templateUrl: 'menu-icons-example.html',
  styleUrls: ['menu-icons-example.css'],
})
export class MenuIconsExample {}

Angular 10 : radio-button Example

Angular 10 : radio-button Example


<mat-radio-button> provides the same functionality as a native <input type="radio"> enhanced with Material Design styling and animations.

All radio-buttons with the same name comprise a set from which only one may be selected at a time.

HTML:


<label id="example-radio-group-label">Pick your favorite season</label>
<mat-radio-group
  aria-labelledby="example-radio-group-label"
  class="example-radio-group"
  [(ngModel)]="favoriteSeason">
  <mat-radio-button class="example-radio-button" *ngFor="let season of seasons" [value]="season">
    {{season}}
  </mat-radio-button>
</mat-radio-group>
<div>Your favorite season is: {{favoriteSeason}}</div>

JavaScript/TS:


<label id="example-radio-group-label">Pick your favorite season</label>
<mat-radio-group
  aria-labelledby="example-radio-group-label"
  class="example-radio-group"
  [(ngModel)]="favoriteSeason">
  <mat-radio-button class="example-radio-button" *ngFor="let season of seasons" [value]="season">
    {{season}}
  </mat-radio-button>
</mat-radio-group>
<div>Your favorite season is: {{favoriteSeason}}</div>

Angular 10 : datepicker Example

Angular 10 : datepicker


The datepicker allows users to enter a date either through text input, or by choosing a date from the calendar. It is made up of several components and directives that work together.

Example:


<mat-form-field appearance="fill">
  <mat-label>Choose a date</mat-label>
  <input matInput [matDatepicker]="picker">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

Angular 10 : Toggle Button Example

Angular 10 : toggle button


<mat-button-toggle> are on/off toggles with the appearance of a button. These toggles can be configured to behave as either radio-buttons or checkboxes. While they can be standalone, they are typically part of a mat-button-toggle-group.

Example:

<mat-button-toggle-group name="fontStyle" aria-label="Font Style">
  <mat-button-toggle value="bold">Bold</mat-button-toggle>
  <mat-button-toggle value="italic">Italic</mat-button-toggle>
  <mat-button-toggle value="underline">Underline</mat-button-toggle>
</mat-button-toggle-group>

Angular 10 : Button example

Angular 10 Button


Angular Material buttons are native <button> or <a> elements enhanced with Material Design styling and ink ripples.

Native <button> and <a> elements are always used in order to provide the most straightforward and accessible experience for users. A <button> element should be used whenever some action is performed. An <a> element should be used whenever the user will navigate to another view.

There are several button variants, each applied as an attribute:

Attribute  

mat-button  
Rectangular text button w/ no elevation

mat-raised-button
Rectangular contained button w/ elevation

mat-flat-button
Rectangular contained button w/ no elevation

mat-stroked-button
Rectangular outlined button w/ no elevation

mat-icon-button
Circular button with a transparent background, meant to contain an icon

mat-fab
Circular button w/ elevation, defaults to theme's accent color

mat-mini-fab
Same as mat-fab but smaller

Example:



<section>
  <div class="example-label">Basic</div>
  <div class="example-button-row">
    <button mat-button>Basic</button>
    <button mat-button color="primary">Primary</button>
    <button mat-button color="accent">Accent</button>
    <button mat-button color="warn">Warn</button>
    <button mat-button disabled>Disabled</button>
    <a mat-button href="https://www.google.com/" target="_blank">Link</a>
  </div>
</section>
<mat-divider></mat-divider>
<section>
  <div class="example-label">Raised</div>
  <div class="example-button-row">
    <button mat-raised-button>Basic</button>
    <button mat-raised-button color="primary">Primary</button>
    <button mat-raised-button color="accent">Accent</button>
    <button mat-raised-button color="warn">Warn</button>
    <button mat-raised-button disabled>Disabled</button>
    <a mat-raised-button href="https://www.google.com/" target="_blank">Link</a>
  </div>
</section>
<mat-divider></mat-divider>
<section>
  <div class="example-label">Stroked</div>
  <div class="example-button-row">
    <button mat-stroked-button>Basic</button>
    <button mat-stroked-button color="primary">Primary</button>
    <button mat-stroked-button color="accent">Accent</button>
    <button mat-stroked-button color="warn">Warn</button>
    <button mat-stroked-button disabled>Disabled</button>
    <a mat-stroked-button href="https://www.google.com/" target="_blank">Link</a>
  </div>
</section>
<mat-divider></mat-divider>
<section>
  <div class="example-label">Flat</div>
  <div class="example-button-row">
    <button mat-flat-button>Basic</button>
    <button mat-flat-button color="primary">Primary</button>
    <button mat-flat-button color="accent">Accent</button>
    <button mat-flat-button color="warn">Warn</button>
    <button mat-flat-button disabled>Disabled</button>
    <a mat-flat-button href="https://www.google.com/" target="_blank">Link</a>
  </div>
</section>
<mat-divider></mat-divider>
<section>
  <div class="example-label">Icon</div>
  <div class="example-button-row">
    <div class="example-flex-container">
      <button mat-icon-button aria-label="Example icon button with a vertical three dot icon">
        <mat-icon>more_vert</mat-icon>
      </button>
      <button mat-icon-button color="primary" aria-label="Example icon button with a home icon">
        <mat-icon>home</mat-icon>
      </button>
      <button mat-icon-button color="accent" aria-label="Example icon button with a menu icon">
        <mat-icon>menu</mat-icon>
      </button>
      <button mat-icon-button color="warn" aria-label="Example icon button with a heart icon">
        <mat-icon>favorite</mat-icon>
      </button>
      <button mat-icon-button disabled aria-label="Example icon button with a open in new tab icon">
        <mat-icon>open_in_new</mat-icon>
      </button>
    </div>
  </div>
</section>
<mat-divider></mat-divider>
<section>
  <div class="example-label">FAB</div>
  <div class="example-button-row">
    <div class="example-flex-container">
      <div class="example-button-container">
        <button mat-fab color="primary" aria-label="Example icon button with a delete icon">
          <mat-icon>delete</mat-icon>
        </button>
      </div>
      <div class="example-button-container">
        <button mat-fab color="accent" aria-label="Example icon button with a bookmark icon">
          <mat-icon>bookmark</mat-icon>
        </button>
      </div>
      <div class="example-button-container">
        <button mat-fab color="warn" aria-label="Example icon button with a home icon">
          <mat-icon>home</mat-icon>
        </button>
      </div>
      <div class="example-button-container">
        <button mat-fab disabled aria-label="Example icon button with a heart icon">
          <mat-icon>favorite</mat-icon>
        </button>
      </div>
    </div>
  </div>
</section>
<mat-divider></mat-divider>
<section>
  <div class="example-label">Mini FAB</div>
  <div class="example-button-row">
    <div class="example-flex-container">
      <div class="example-button-container">
        <button mat-mini-fab color="primary" aria-label="Example icon button with a menu icon">
          <mat-icon>menu</mat-icon>
        </button>
      </div>
      <div class="example-button-container">
        <button mat-mini-fab color="accent" aria-label="Example icon button with a plus one icon">
          <mat-icon>plus_one</mat-icon>
        </button>
      </div>
      <div class="example-button-container">
        <button mat-mini-fab color="warn" aria-label="Example icon button with a filter list icon">
          <mat-icon>filter_list</mat-icon>
        </button>
      </div>
      <div class="example-button-container">
        <button mat-mini-fab disabled aria-label="Example icon button with a home icon">
          <mat-icon>home</mat-icon>
        </button>
      </div>
    </div>
  </div>
</section>

Spring Batch - Use bulk writes in MongoItemWriter

Use bulk writes in MongoItemWriter

Up until now, the MongoItemWriter used MongoOperations.save() in a for loop to save items to the database. In this release, we replaced this mechanism with a single call to BulkOperations. With this change, the MongotItemWriter is 25x faster than the previous version, according to benchmark mongo-item-writer-benchmark.

Use of bulk writes in RepositoryItemWriter

Up to spring-batch version 4.2, it was required to specify the method name to use to save an item to the database. This method was then called in a for loop to save all items. In order to use CrudRepository.saveAll, it was required to extend RepositoryItemWriter and override write(List), which is not convenient.

In spring-batch v4.3.0 release, RepositoryItemWriter use CrudRepository.saveAll by default. This changes improves the performance of the writer by a factor of 2, according to our benchmark repository-item-writer-benchmark.

Configuration of Spring Batch tests with JUnit 5

Configuration of Spring Batch tests with JUnit 5

Similar to how many Spring Boot test annotations are meta-annotated with @ExtendWith(SpringExtension.class) (like @SpringBootTest, @WebMvcTest, and others), we updated @SpringBatchTest to be meta-annotated with @ExtendWith(SpringExtension.class).

This simplifies the configuration when writing tests with JUnit Jupiter.

Please note that this feature does not affect JUnit 4 users, it only concerns JUnit 5 based tests.

Spring Batch JpaPagingItemReader Example

JpaPagingItemReader

Spring Batch 4.3.0 Add support for named queries in JpaPagingItemReader.

Up until now, it was possible to use named queries with the JpaPagingItemReader. However, this required the creation of a custom query provider, as follows:

JpaPagingItemReader<Foo> reader = new JpaPagingItemReaderBuilder<Foo>()
    .name("fooReader")
    .queryProvider(new AbstractJpaQueryProvider() {
       @Override
       public Query createQuery() {
          return getEntityManager().createNamedQuery("allFoos", Foo.class);
       }

       @Override
       public void afterPropertiesSet() throws Exception {
       }
    })
    // set other properties on the reader
    .build();

In this release, we introduced a JpaNamedQueryProvider next to the JpaNativeQueryProvider
to ease the configuration, which can now be written like this:

JpaPagingItemReader<Foo> reader = new JpaPagingItemReaderBuilder<Foo>()
.name("fooReader")
.queryProvider(new JpaNamedQueryProvider("allFoos", Foo.class))
// set other properties on the reader
.build();

Hibernate JPA @OrderBy Example

@OrderBy

The @OrderBy annotation is used to specify a SQL ordering directive for sorting the currently annotated collection.

It differs from the JPA @OrderBy annotation because the JPA annotation expects a JPQL order-by fragment, not an SQL directive.

OrderBy
Order a collection using SQL ordering (not HQL ordering). Different from OrderBy in that this expects SQL fragment, JPA OrderBy expects a valid JPQL order-by fragment.

Customizing ORDER BY SQL clause
While the JPA @OrderBy annotation allows you to specify the entity attributes used for sorting when fetching the current annotated collection, the Hibernate specific @OrderBy annotation is used to specify a SQL clause instead.

In the following example, the @OrderBy annotation uses the CHAR_LENGTH SQL function to order the Article entities by the number of characters of the name attribute.

Example : @OrderBy mapping example

@Entity(name = "Person")
public static class Person {

@Id
private Long id;

private String name;

@OneToMany(
mappedBy = "person",
cascade = CascadeType.ALL
)
@org.hibernate.annotations.OrderBy(
clause = "CHAR_LENGTH(name) DESC"
)
private List<Article> articles = new ArrayList<>();

//Getters and setters are omitted for brevity
}

@Entity(name = "Article")
public static class Article {

@Id
@GeneratedValue
private Long id;

private String name;

private String content;

@ManyToOne(fetch = FetchType.LAZY)
private Person person;

//Getters and setters are omitted for brevity
}

Hibernate JPA @OptimisticLocking Example

@OptimisticLocking

The @OptimisticLocking annotation is used to specify the currently annotated entity’s optimistic locking strategy.

The four possible strategies are defined by the OptimisticLockType enumeration:

NONE
The implicit optimistic locking mechanism is disabled.

VERSION
The implicit optimistic locking mechanism is using a dedicated version column.

ALL
The implicit optimistic locking mechanism is using all attributes as part of an expanded WHERE clause restriction for the UPDATE and DELETE SQL statements.

DIRTY
The implicit optimistic locking mechanism is using the dirty attributes (the attributes that were modified) as part of an expanded WHERE clause restriction for the UPDATE and DELETE SQL statements.

OptimisticLocking

Used to define the style of optimistic locking to be applied to an entity. In a hierarchy, only valid on the root entity.

Versionless optimistic locking

Although the default @Version property optimistic locking mechanism is sufficient in many situations, sometimes, you need rely on the actual database row column values to prevent lost updates.

Hibernate supports a form of optimistic locking that does not require a dedicated "version attribute". This is also useful for use with modeling legacy schemas.

The idea is that you can get Hibernate to perform "version checks" using either all of the entity’s attributes or just the attributes that have changed. This is achieved through the use of the @OptimisticLocking annotation which defines a single attribute of type org.hibernate.annotations.OptimisticLockType.

There are 4 available OptimisticLockTypes:


NONE
optimistic locking is disabled even if there is a @Version annotation present

VERSION (the default)
performs optimistic locking based on a @Version as described above

ALL
performs optimistic locking based on all fields as part of an expanded WHERE clause restriction for the UPDATE/DELETE SQL statements

DIRTY
performs optimistic locking based on dirty fields as part of an expanded WHERE clause restriction for the UPDATE/DELETE SQL statements

Versionless optimistic locking using OptimisticLockType.ALL

Example : OptimisticLockType.ALL mapping example

@Entity(name = "Person")
@OptimisticLocking(type = OptimisticLockType.ALL)
@DynamicUpdate
public static class Person {

@Id
private Long id;

@Column(name = "`name`")
private String name;

private String country;

private String city;

@Column(name = "created_on")
private Timestamp createdOn;

//Getters and setters are omitted for brevity
}

Hibernate JPA @OptimisticLock Example

@OptimisticLock

The @OptimisticLock annotation is used to specify if the currently annotated attribute will trigger an entity version increment upon being modified.

OptimisticLock
Whether or not a change of the annotated property will trigger an entity version increment. If the annotation is not present, the property is involved in the optimistic lock strategy (default).

Excluding attributes

By default, every entity attribute modification is going to trigger a version incrementation. If there is an entity property which should not bump up the entity version, then you need to annotate it with the Hibernate @OptimisticLock annotation, as illustrated in the following example.

Example : @OptimisticLock mapping example

@Entity(name = "Phone")
public static class Phone {

@Id
private Long id;

@Column(name = "`number`")
private String number;

@OptimisticLock( excluded = true )
private long callCount;

@Version
private Long version;

//Getters and setters are omitted for brevity

public void incrementCallCount() {
this.callCount++;
}
}

Hibernate JPA @OnDelete Example

@OnDelete

The @OnDelete annotation is used to specify the delete strategy employed by the currently annotated collection, array or joined subclasses. This annotation is used by the automated schema generation tool to generated the appropriate FOREIGN KEY DDL cascade directive.

The two possible strategies are defined by the OnDeleteAction enumeration:

CASCADE
Use the database FOREIGN KEY cascade capabilities.

NO_ACTION
Take no action.

OnDelete
Strategy to use on collections, arrays and on joined subclasses delete. OnDelete of secondary tables currently not supported.

@OnDelete cascade

While the previous cascade types propagate entity state transitions, the @OnDelete cascade is a DDL-level FK feature which allows you to remove a child record whenever the parent row is deleted.

So, when annotating the @ManyToOne association with @OnDelete( action = OnDeleteAction.CASCADE ), the automatic schema generator will apply the ON DELETE CASCADE SQL directive to the Foreign Key declaration, as illustrated by the following example.

Example : @OnDelete @ManyToOne mapping

@Entity(name = "Person")
public static class Person {

@Id
private Long id;

private String name;

//Getters and setters are omitted for brevity

}
@Entity(name = "Phone")
public static class Phone {

@Id
private Long id;

@Column(name = "`number`")
private String number;

@ManyToOne(fetch = FetchType.LAZY)
@OnDelete( action = OnDeleteAction.CASCADE )
private Person owner;

//Getters and setters are omitted for brevity

}

@OnDelete @OneToMany mapping

@Entity(name = "Person")
public static class Person {

@Id
private Long id;

private String name;

@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
@OnDelete(action = OnDeleteAction.CASCADE)
private List<Phone> phones = new ArrayList<>();

//Getters and setters are omitted for brevity

}
@Entity(name = "Phone")
public static class Phone {

@Id
private Long id;

@Column(name = "`number`")
private String number;

@ManyToOne(fetch = FetchType.LAZY)
private Person owner;

//Getters and setters are omitted for brevity

}

Hibernate JPA @NotFound Example

@NotFound

The @NotFound annotation is used to specify the NotFoundAction strategy for when an element is not found in a given association.

NotFound
Action to do when an element is not found on a association.

The NotFoundAction defines two possibilities:


EXCEPTION
An exception is thrown when an element is not found (default and recommended).

IGNORE
Ignore the element when not found in the database.

@NotFound association mapping

When dealing with associations which are not enforced by a Foreign Key, it’s possible to bump into inconsistencies if the child record cannot reference a parent entity.

By default, Hibernate will complain whenever a child association references a non-existing parent record. However, you can configure this behavior so that Hibernate can ignore such an Exception and simply assign null as a parent object referenced.

To ignore non-existing parent entity references, even though not really recommended, it’s possible to use the annotation org.hibernate.annotation.NotFound annotation with a value of org.hibernate.annotations.NotFoundAction.IGNORE.

The @ManyToOne and @OneToOne associations that are annotated with @NotFound(action = NotFoundAction.IGNORE) are always fetched eagerly even if the fetch strategy is set to FetchType.LAZY.

Considering the following City and Person entity mappings:

Example : @NotFound mapping example

@Entity
@Table( name = "Person" )
public static class Person {

@Id
private Long id;

private String name;

private String cityName;

@ManyToOne
@NotFound ( action = NotFoundAction.IGNORE )
@JoinColumn(
name = "cityName",
referencedColumnName = "name",
insertable = false,
updatable = false
)
private City city;

//Getters and setters are omitted for brevity

}

@Entity
@Table( name = "City" )
public static class City implements Serializable {

@Id
@GeneratedValue
private Long id;

private String name;

//Getters and setters are omitted for brevity

}

Hibernate JPA @NaturalIdCache Example

@NaturalIdCache

The @NaturalIdCache annotation is used to specify that the natural id values associated with the annotated entity should be stored in the second-level cache.

NaturalIdCache
Used to specify that the natural id values associated with the annotated entity should be cached in Hibernate's shared (L2) cache. Can optionally name a custom cache region.

Natural id caching

@Entity(name = "Book")
@NaturalIdCache
public static class Book {

@Id
private Long id;

private String title;

private String author;

@NaturalId
private String isbn;

//Getters and setters are omitted for brevity
}

Hibernate JPA @NaturalId Example

@NaturalId

The @NaturalId annotation is used to specify that the currently annotated attribute is part of the natural id of the entity.

NaturalId
This specifies that a property is part of the natural id of the entity.

Natural Ids

Natural ids represent domain model unique identifiers that have a meaning in the real world too. Even if a natural id does not make a good primary key (surrogate keys being usually preferred), it’s still useful to tell Hibernate about it. As we will see later, Hibernate provides a dedicated, efficient API for loading an entity by its natural id much like it offers for loading by its identifier (PK).

Natural Id Mapping

Natural ids are defined in terms of one or more persistent attributes.

Example : Natural id using single basic attribute
@Entity(name = "Book")
public static class Book {

@Id
private Long id;

private String title;

private String author;

@NaturalId
private String isbn;

//Getters and setters are omitted for brevity
}
Example : Natural id using single embedded attribute
@Entity(name = "Book")
public static class Book {

@Id
private Long id;

private String title;

private String author;

@NaturalId
@Embedded
private Isbn isbn;

//Getters and setters are omitted for brevity
}

@Embeddable
public static class Isbn implements Serializable {

private String isbn10;

private String isbn13;

//Getters and setters are omitted for brevity

@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Isbn isbn = (Isbn) o;
return Objects.equals( isbn10, isbn.isbn10 ) &&
Objects.equals( isbn13, isbn.isbn13 );
}

@Override
public int hashCode() {
return Objects.hash( isbn10, isbn13 );
}
}
Example : Natural id using multiple persistent attributes
@Entity(name = "Book")
public static class Book {

@Id
private Long id;

private String title;

private String author;

@NaturalId
private String productNumber;

@NaturalId
@ManyToOne(fetch = FetchType.LAZY)
private Publisher publisher;

//Getters and setters are omitted for brevity
}

@Entity(name = "Publisher")
public static class Publisher implements Serializable {

@Id
private Long id;

private String name;

//Getters and setters are omitted for brevity

@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Publisher publisher = (Publisher) o;
return Objects.equals( id, publisher.id ) &&
Objects.equals( name, publisher.name );
}

@Override
public int hashCode() {
return Objects.hash( id, name );
}
}

Natural Id API

As stated before, Hibernate provides an API for loading entities by their associated natural id. This is represented by the org.hibernate.NaturalIdLoadAccess contract obtained via Session#byNaturalId.

If the entity does not define a natural id, trying to load an entity by its natural id will throw an exception.

Example :Using NaturalIdLoadAccess
Book book = entityManager
.unwrap(Session.class)
.byNaturalId( Book.class )
.using( "isbn", "978-9730228236" )
.load();
Book book = entityManager
.unwrap(Session.class)
.byNaturalId( Book.class )
.using(
"isbn",
new Isbn(
"973022823X",
"978-9730228236"
) )
.load();
Book book = entityManager
.unwrap(Session.class)
.byNaturalId( Book.class )
.using("productNumber", "973022823X")
.using("publisher", publisher)
.load();

NaturalIdLoadAccess offers 2 distinct methods for obtaining the entity:

load()

obtains a reference to the entity, making sure that the entity state is initialized.

getReference()

obtains a reference to the entity. The state may or may not be initialized. If the entity is already associated with the current running Session, that reference (loaded or not) is returned. If the entity is not loaded in the current Session and the entity supports proxy generation, an uninitialized proxy is generated and returned, otherwise the entity is loaded from the database and returned.

NaturalIdLoadAccess allows loading an entity by natural id and at the same time applies a pessimistic lock. For additional details on locking, see the Locking chapter.

We will discuss the last method available on NaturalIdLoadAccess ( setSynchronizationEnabled() ) in Natural Id - Mutability and Caching.

Because the Book entities in the first two examples define "simple" natural ids, we can load them as follows:

Example : Loading by simple natural id
Book book = entityManager
.unwrap(Session.class)
.bySimpleNaturalId( Book.class )
.load( "978-9730228236" );
Book book = entityManager
.unwrap(Session.class)
.bySimpleNaturalId( Book.class )
.load(
new Isbn(
"973022823X",
"978-9730228236"
)
);
Here we see the use of the org.hibernate.SimpleNaturalIdLoadAccess contract, obtained via Session#bySimpleNaturalId().

SimpleNaturalIdLoadAccess is similar to NaturalIdLoadAccess except that it does not define the using method. Instead, because these simple natural ids are defined based on just one attribute we can directly pass the corresponding natural id attribute value directly to the load() and getReference() methods.

If the entity does not define a natural id, or if the natural id is not of a "simple" type, an exception will be thrown there.

Natural Id - Mutability and Caching

A natural id may be mutable or immutable. By default the @NaturalId annotation marks an immutable natural id attribute. An immutable natural id is expected to never change its value.

If the value(s) of the natural id attribute(s) change, @NaturalId(mutable = true) should be used instead.

Example : Mutable natural id mapping
@Entity(name = "Author")
public static class Author {

@Id
private Long id;

private String name;

@NaturalId(mutable = true)
private String email;

//Getters and setters are omitted for brevity
}
Within the Session, Hibernate maintains a mapping from natural id values to entity identifiers (PK) values. If natural ids values changed, it is possible for this mapping to become out of date until a flush occurs.

To work around this condition, Hibernate will attempt to discover any such pending changes and adjust them when the load() or getReference() methods are executed. To be clear: this is only pertinent for mutable natural ids.

This discovery and adjustment have a performance impact. If you are certain that none of the mutable natural ids already associated with the current Session have changed, you can disable this checking by calling setSynchronizationEnabled(false) (the default is true). This will force Hibernate to circumvent the checking of mutable natural ids.

Example : Mutable natural id synchronization use-case
Author author = entityManager
.unwrap(Session.class)
.bySimpleNaturalId( Author.class )
.load( "john@acme.com" );

author.setEmail( "john.doe@acme.com" );

assertNull(
entityManager
.unwrap(Session.class)
.bySimpleNaturalId( Author.class )
.setSynchronizationEnabled( false )
.load( "john.doe@acme.com" )
);

assertSame( author,
entityManager
.unwrap(Session.class)
.bySimpleNaturalId( Author.class )
.setSynchronizationEnabled( true )
.load( "john.doe@acme.com" )
);
Not only can this NaturalId-to-PK resolution be cached in the Session, but we can also have it cached in the second-level cache if second level caching is enabled.

Example : Natural id caching
@Entity(name = "Book")
@NaturalIdCache
public static class Book {

@Id
private Long id;

private String title;

private String author;

@NaturalId
private String isbn;

//Getters and setters are omitted for brevity
}

Hibernate JPA @Nationalized Example

@Nationalized

The @Nationalized annotation is used to specify that the currently annotated attribute is a character type (e.g. String, Character, Clob) that is stored in a nationalized column type (NVARCHAR, NCHAR, NCLOB).

Nationalized

Marks a character data type (String, Character, character, Clob) as being a nationalized variant (NVARCHAR, NCHAR, NCLOB, etc).

Mapping Nationalized Character Data

JDBC 4 added the ability to explicitly handle nationalized character data. To this end, it added specific nationalized character data types:

NCHAR

NVARCHAR

LONGNVARCHAR

NCLOB

Considering we have the following database table:

Example 46. NVARCHAR - SQL
CREATE TABLE Product (
    id INTEGER NOT NULL ,
    name VARCHAR(255) ,
    warranty NVARCHAR(255) ,
    PRIMARY KEY ( id )
)
To map a specific attribute to a nationalized variant data type, Hibernate defines the @Nationalized annotation.

Example : NVARCHAR mapping

@Entity(name = "Product")
public static class Product {

    @Id
    private Integer id;

    private String name;

    @Nationalized
    private String warranty;

    //Getters and setters are omitted for brevity

}
Just like with CLOB, Hibernate can also deal with NCLOB SQL data types:

Example : NCLOB - SQL

CREATE TABLE Product (
    id INTEGER NOT NULL ,
    name VARCHAR(255) ,
    warranty nclob ,
    PRIMARY KEY ( id )
)
Hibernate can map the NCLOB to a java.sql.NClob

Example : NCLOB mapped to java.sql.NClob

@Entity(name = "Product")
public static class Product {

    @Id
    private Integer id;

    private String name;

    @Lob
    @Nationalized
    // Clob also works, because NClob extends Clob.
    // The database type is still NCLOB either way and handled as such.
    private NClob warranty;

    //Getters and setters are omitted for brevity

}
To persist such an entity, you have to create an NClob using the NClobProxy Hibernate utility:

Example : Persisting a java.sql.NClob entity

String warranty = "My product warranty";

final Product product = new Product();
product.setId( 1 );
product.setName( "Mobile phone" );

product.setWarranty( NClobProxy.generateProxy( warranty ) );

entityManager.persist( product );
To retrieve the NClob content, you need to transform the underlying java.io.Reader:

Example 51. Returning a java.sql.NClob entity
Product product = entityManager.find( Product.class, productId );

try (Reader reader = product.getWarranty().getCharacterStream()) {
    assertEquals( "My product warranty", toString( reader ) );
}
We could also map the NCLOB in a materialized form. This way, we can either use a String or a char[].

Example : NCLOB mapped to String

@Entity(name = "Product")
public static class Product {

    @Id
    private Integer id;

    private String name;

    @Lob
    @Nationalized
    private String warranty;

    //Getters and setters are omitted for brevity

}
We might even want the materialized data as a char array.

Example : NCLOB - materialized char[] mapping

@Entity(name = "Product")
public static class Product {

    @Id
    private Integer id;

    private String name;

    @Lob
    @Nationalized
    private char[] warranty;

    //Getters and setters are omitted for brevity

}

Hibernate JPA @NamedQuery Example

@NamedQuery

The @NamedQuery annotation extends the JPA @NamedQuery with Hibernate specific features, like:

  • flush mode for this particular query
  • if the query should be cached, and which cache region should be used
  • the selected entity CacheModeType strategy
  • the JDBC Statement fetch size
  • the JDBC Statement execution timeout
  • if the query is a CallableStatement, targeting a stored procedure or a database function
  • what SQL-level comment should be sent to the database
  • if the query is read-only, hence it does not store the resulted entities into the currently running Persistence Context

NamedQuery

Specifies a static, named query in the Java Persistence query language. Query names are scoped to the persistence unit. The NamedQuery annotation can be applied to an entity or mapped superclass.
The following is an example of the definition of a named query in the Java Persistence query language:

    @NamedQuery(
            name="findAllCustomersWithName",
            query="SELECT c FROM Customer c WHERE c.name LIKE :custName"
    )

The following is an example of the use of a named query:

    @PersistenceContext
    public EntityManager em;
    ...
    customers = em.createNamedQuery("findAllCustomersWithName")
            .setParameter("custName", "Smith")
            .getResultList();

@NamedQueries({
    @NamedQuery(
        name = "get_phone_by_number",
        query = "select p " +
                "from Phone p " +
                "where p.number = :number",
        timeout = 1,
        readOnly = true
    )
})

Hibernate JPA @NamedNativeQuery Example

@NamedNativeQuery

The @NamedNativeQuery annotation extends the JPA @NamedNativeQuery with Hibernate specific features, like:


  • flush mode for this particular query
  • if the query should be cached, and which cache region should be used
  • the selected entity CacheModeType strategy
  • the JDBC Statement fetch size
  • the JDBC Statement execution timeout
  • if the query is a CallableStatement, targeting a stored procedure or a database function
  • what SQL-level comment should be sent to the database


if the query is read-only, hence it does not store the resulted entities into the currently running Persistence Context

 Hibernate NamedNativeQuery

@NamedNativeQueries({
    @NamedNativeQuery(
        name = "get_person_phone_count",
        query = "SELECT pr.name AS name, count(*) AS phoneCount " +
                "FROM Phone p " +
                "JOIN Person pr ON pr.id = p.person_id " +
                "GROUP BY pr.name",
        resultSetMapping = "person_phone_count",
        timeout = 1,
        readOnly = true
    ),
})
@SqlResultSetMapping(
    name = "person_phone_count",
    classes = @ConstructorResult(
        targetClass = PersonPhoneCount.class,
        columns = {
            @ColumnResult(name = "name"),
            @ColumnResult(name = "phoneCount")
        }
    )
)

Hibernate JPA @MetaValue Eample

@MetaValue

The @MetaValue annotation is used by the @AnyMetaDef annotation to specify the association between a given discriminator value and an entity type.

MetaValue

Maps a given discriminator value to the corresponding entity type. See Any for more information.

Any

Defines a ToOne-style association pointing to one of several entity types depending on a local discriminator, as opposed to discriminated inheritance where the discriminator is kept as part of the entity hierarchy. For example, if you consider an Order entity containing Payment information where Payment might be of type CashPayment or CreditCardPayment the @Any approach would be to keep that discriminator and matching value on the Order itself. Thought of another way, the "foreign-key" really is made up of the value and discriminator (there is no physical foreign key here as databases do not support this):
    @Entity
    class Order {
        ...
        @Any( metaColumn = @Column( name="payment_type" ) )
        @AnyMetDef(
                idType = "long"
                metaValues = {
                        @MetaValue( value="C", targetEntity=CashPayment.class ),
                        @MetaValue( value="CC", targetEntity=CreditCardPayment.class ),
                }
        )
        pubic Payment getPayment() { ... }
    }
 }


@Any mapping

The @Any mapping is useful to emulate a unidirectional @ManyToOne association when there can be multiple target entities.

Because the @Any mapping defines a polymorphic association to classes from multiple tables, this association type requires the FK column which provides the associated parent identifier and a metadata information for the associated entity type.

The @Any annotation describes the column holding the metadata information. To link the value of the metadata information and an actual entity type, the @AnyDef and @AnyDefs annotations are used. The metaType attribute allows the application to specify a custom type that maps database column values to persistent classes that have identifier properties of the type specified by idType. You must specify the mapping from values of the metaType to class names.

@Any mapping usage

@Entity
@Table( name = "property_holder" )
public class PropertyHolder {

    @Id
    private Long id;

    @Any(
        metaDef = "PropertyMetaDef",
        metaColumn = @Column( name = "property_type" )
    )
    @JoinColumn( name = "property_id" )
    private Property property;

    //Getters and setters are omitted for brevity

}

Hibernate JPA @MapKeyType Example

@MapKeyType

The @MapKeyType annotation is used to specify the map key type.

MapKeyType
Allows defining the type of the key of a persistent map.

@MapKeyType mapping example

@Entity
@Table(name = "person")
public static class Person {

@Id
private Long id;

@ElementCollection
@CollectionTable(
name = "call_register",
joinColumns = @JoinColumn(name = "person_id")
)
@MapKeyType(
@Type(
type = "org.hibernate.userguide.collections.type.TimestampEpochType"
)
)
@MapKeyColumn( name = "call_timestamp_epoch" )
@Column(name = "phone_number")
private Map<Date, Integer> callRegister = new HashMap<>();

//Getters and setters are omitted for brevity

}

2020-06-26

Version 10 of Angular Now Available | What's new in Angular 10?

Angular Version 10 Released! This is a major release that spans the entire platform, including the framework, Angular Material, and the CLI.

What’s in Angular 10 release?

New Date Range Picker

Angular Material now includes a new date range picker.

<mat-form-field>
  <mat-label>Enter a date range</mat-label>
  <mat-date-range-input [rangePicker]="picker">
    <input matStartDate matInput placeholder="Start date">
    <input matEndDate matInput placeholder="End date">
  </mat-date-range-input>
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-date-range-picker #picker></mat-date-range-picker>
</mat-form-field>

To use the new date range picker, you can use the mat-date-range-input and mat-date-range-picker components.

Warnings about CommonJS imports

When you use a dependency that is packaged with CommonJS, it can result in larger slower applications.
Starting with version 10, we now warn you when your build pulls in one of these bundles. If you’ve started seeing these warnings for your dependencies, let your dependency know that you’d prefer an ECMAScript module (ESM) bundle.

Optional Stricter Settings

Version 10 offers a more strict project setup when you create a new workspace with ng new.

ng new --strict

Enabling this flag initializes your new project with a few new settings that improve maintainability, help you catch bugs ahead of time, and allow the CLI to perform advanced optimizations on your app. Specifically, the strict flag does the following:

  • Enables strict mode in TypeScript
  • Turns template type checking to Strict
  • Default bundle budgets have been reduced by ~75%
  • Configures linting rules to prevent declarations of type any
  • Configures your app as side-effect free to enable more advanced tree-shaking


Keeping Up to Date with the Ecosystem

As usual, we have made a few updates to the dependencies of Angular to stay synchronized with the JavaScript ecosystem.

  • TypeScript bumped to TypeScript 3.9
  • TSLib has been updated to v2.0
  • TSLint has been updated to v6

Angular 10 also updated our project layout. Starting with version 10 you will see a new tsconfig.base.json. This additional tsconfig.json file better supports the way that IDEs and build tooling resolve type and package configurations.

2020-06-25

Hibernate JPA @Loader Example

@Loader

The @Loader annotation is used to override the default SELECT query used for loading an entity.

Loader

Used to override how Hibernate performs load operations. naming a named query to use instead of its generated SELECT SQL.

Custom CRUD

@Entity(name = "Person")
@SQLInsert(
sql = "INSERT INTO person (name, id, valid) VALUES (?, ?, true) ",
check = ResultCheckStyle.COUNT
)
@SQLUpdate(
sql = "UPDATE person SET name = ? where id = ? "
)
@SQLDelete(
sql = "UPDATE person SET valid = false WHERE id = ? "
)
@Loader(namedQuery = "find_valid_person")
@NamedNativeQueries({
@NamedNativeQuery(
name = "find_valid_person",
query = "SELECT id, name " +
"FROM person " +
"WHERE id = ? and valid = true",
resultClass = Person.class
)
})
public static class Person {

@Id
@GeneratedValue
private Long id;

private String name;

@ElementCollection
@SQLInsert(
sql = "INSERT INTO person_phones (person_id, phones, valid) VALUES (?, ?, true) ")
@SQLDeleteAll(
sql = "UPDATE person_phones SET valid = false WHERE person_id = ?")
@Where( clause = "valid = true" )
private List<String> phones = new ArrayList<>();

//Getters and setters are omitted for brevity

}
In the example above, the entity is mapped so that entries are soft-deleted (the records are not removed from the database, but instead, a flag marks the row validity). The Person entity benefits from custom INSERT, UPDATE, and DELETE statements which update the valid column accordingly. The custom @Loader is used to retrieve only Person rows that are valid.

Hibernate JPA @ListIndexBase Example

@ListIndexBase

The @ListIndexBase annotation is used to specify the start value for a list index, as stored in the database.

By default, List indexes are stored starting at zero. Generally used in conjunction with @OrderColumn.

ListIndexBase

Defines the start index value for a list index as stored on the database. This base is subtracted from the incoming database value on reads to determine the List position; it is added to the List position index when writing to the database. By default list indexes are stored starting at zero. Generally used in conjunction with OrderColumn.

Customizing ordered list ordinal

You can customize the ordinal of the underlying ordered list by using the @ListIndexBase annotation.

Example : @ListIndexBase mapping example

@OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
@OrderColumn(name = "order_id")
@ListIndexBase(100)
private List<Phone> phones = new ArrayList<>();

When inserting two Phone records, Hibernate is going to start the List index from 100 this time.

2020-06-24

Hibernate JPA @LazyToOne Example

@LazyToOne

The @LazyToOne annotation is used to specify the laziness options, represented by LazyToOneOption, available for a @OneToOne or @ManyToOne association.

LazyToOne Define the laziness options available for a ToOne (ie OneToOne or ManyToOne) association.

LazyToOneOption defines the following alternatives:

FALSE
Eagerly load the association. This one is not needed since the JPA FetchType.EAGER offers the same behavior.

NO_PROXY
This option will fetch the association lazily while returning real entity object.

PROXY
This option will fetch the association lazily while returning a proxy instead.


Bidirectional @OneToOne lazy association

Although you might annotate the parent-side association to be fetched lazily, Hibernate cannot honor this request since it cannot know whether the association is null or not.

The only way to figure out whether there is an associated record on the child side is to fetch the child association using a secondary query. Because this can lead to N+1 query issues, it’s much more efficient to use unidirectional @OneToOne associations with the @MapsId annotation in place.

However, if you really need to use a bidirectional association and want to make sure that this is always going to be fetched lazily, then you need to enable lazy state initialization bytecode enhancement and use the @LazyToOne annotation as well.

Example - Bidirectional @OneToOne lazy parent-side association

@Entity(name = "Phone")
public static class Phone {

@Id
@GeneratedValue
private Long id;

@Column(name = "`number`")
private String number;

@OneToOne(
mappedBy = "phone",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
@LazyToOne( LazyToOneOption.NO_PROXY )
private PhoneDetails details;

//Getters and setters are omitted for brevity

public void addDetails(PhoneDetails details) {
details.setPhone( this );
this.details = details;
}

public void removeDetails() {
if ( details != null ) {
details.setPhone( null );
this.details = null;
}
}
}

@Entity(name = "PhoneDetails")
public static class PhoneDetails {

@Id
@GeneratedValue
private Long id;

private String provider;

private String technology;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "phone_id")
private Phone phone;

//Getters and setters are omitted for brevity

}

Hibernate JPA @LazyGroup Example

@LazyGroup

The @LazyGroup annotation is used to specify that an entity attribute should be fetched along with all the other attributes belonging to the same group.

To load entity attributes lazily, bytecode enhancement is needed. By default, all non-collection attributes are loaded in one group named "DEFAULT".

This annotation allows defining different groups of attributes to be initialized together when access one attribute in the group.

LazyGroup

For use with bytecode-enhanced lazy-loading support.
Identifies grouping for performing lazy attribute loading. By default all non-collection attributes are loaded in one group named "DEFAULT". This annotation allows defining different groups of attributes to be initialized together when access one attribute in the group.

@LazyGroup example

@Entity
public class Customer {

@Id
private Integer id;

private String name;

@Basic( fetch = FetchType.LAZY )
private UUID accountsPayableXrefId;

@Lob
@Basic( fetch = FetchType.LAZY )
@LazyGroup( "lobs" )
private Blob image;

//Getters and setters are omitted for brevity

}

2020-06-22

Convert JSON To Class Object In Java

Convert JSON To Class Object In Java


In this example we will see how to convert json string to java object with spring framework and jackson apis.

Example:


Json:

String name=
"{
"name" : "Text1"
}";

Create a class for json attribute:

class User{
String name;
}

import com.fasterxml.jackson.anotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

public class ConvertJsonToJavaClassObject{

public static void main(String args[]){
String userString = //json string

ObjectMapper objectMapper = new Jackson2ObjectMapperBuilder().build();
User user = objectMapper.readValue(userString, User.class);

}
}



JSON to Collection object:

json to list:

Jsong string:

String name =

{
users:[{
"name" :"name1"
},
{
"name" :"name2"
}
]
}

Java Example:
class Users {
List<User> users;
}

String userString = //json string

ObjectMapper objectMapper = new Jackson2ObjectMapperBuilder().build();

CollectionType type = objectMapper .getTypeFactory().constructCollectionType(List.class, Users .class);
User user = objectMapper.readValue(userString, type);