////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Using Blaze-Persistence

include::./attributes.adoc[]
:config-file: application.properties

Blaze-Persistence offers a fluent query builder API on top of JPA with a deep Hibernate ORM integration that enables the
use of advanced SQL features like Common Table Expressions while staying in the realm of the JPA model.

On top of that, the Blaze-Persistence Entity-View module allows for DTO definitions that can be applied to business logic
queries which are then transformed to optimized queries that only fetch the data that is needed to construct the DTO instances.
The same DTO definitions can further be used for applying database updates, leading to a great reduction in boilerplate
code and removing the need for object mapping tools.

include::./platform-include.adoc[]

== Setting up and configuring Blaze-Persistence

The extension comes with default producers for `CriteriaBuilderFactory` and `EntityViewManager` that work out of the
box given a working Hibernate ORM configuration. For customization, overriding of the default producers is possible via the
standard mechanism as documented in the link:{quarkus-home-url}/guides/cdi-reference#default_beans[Quarkus CDI reference].
This is needed if you need to set custom link:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#anchor-configuration-properties[Blaze-Persistence properties].

In Quarkus, you just need to:

* `@Inject` `CriteriaBuilderFactory` or `EntityViewManager` and use it
* annotate your entity views with `@EntityView` and any other mapping annotation as usual

Add the following dependencies to your project:

* the Blaze-Persistence extension: `com.blazebit:blaze-persistence-integration-quarkus`
* further Blaze-Persistence integrations as needed:
  - `blaze-persistence-integration-jackson` for link:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#Jackson%20integration[Jackson]
  - `blaze-persistence-integration-jaxrs` for link:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#jaxrs-integration[JAX-RS]


[source,xml]
.Example dependencies using Maven
----
<dependencies>
    <!-- Blaze-Persistence specific dependencies -->
    <dependency>
        <groupId>com.blazebit</groupId>
        <artifactId>blaze-persistence-integration-quarkus</artifactId>
    </dependency>
    <dependency>
        <groupId>com.blazebit</groupId>
        <artifactId>blaze-persistence-integration-hibernate-5.4</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>
----

The use in native images requires a dependency on the entity view annotation processor that may be extracted into a separate `native` profile:

[source,xml]
----
<profiles>
    <profile>
        <id>native</id>
        <dependencies>
            <dependency>
                <groupId>com.blazebit</groupId>
                <artifactId>blaze-persistence-entity-view-processor</artifactId>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </profile>
</profiles>
----

A `CriteriaBuilderFactory` and an `EntityViewManager` will be created based on the configured `EntityManagerFactory` as provided by the link:{quarkus-home-url}/guides/hibernate-orm[Hibernate-ORM extension].

You can then access these beans via injection:

[source,java]
.Example application bean using Hibernate
----
@ApplicationScoped
public class SantaClausService {
    @Inject
    EntityManager em; <1>
    @Inject
    CriteriaBuilderFactory cbf; <2>
    @Inject
    EntityViewManager evm; <3>

    @Transactional <4>
    public List<GiftView> findAllGifts() {
        CriteriaBuilder<Gift> cb = cbf.create(em, Gift.class);
        return evm.applySetting(EntityViewSetting.create(GiftView.class), cb).getResultList();
    }
}
----

<1> Inject the `EntityManager`
<2> Inject the `CriteriaBuilderFactory`
<3> Inject the `EntityViewManager`
<4> Mark your CDI bean method as `@Transactional` so that a transaction is started or joined.

[source,java]
.Example Entity
----
@Entity
public class Gift {
    private Long id;
    private String name;
    private String description;

    @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="giftSeq")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}
----

[source,java]
.Example Entity-View
----
@EntityView(Gift.class)
public interface GiftView {

    @IdMapping
    Long getId();

    String getName();
}
----

[source,java]
.Example updatable Entity-View
----
@UpdatableEntityView
@CreatableEntityView
@EntityView(Gift.class)
public interface GiftUpdateView extends GiftView {

    void setName(String name);
}
----

[source,java]
.Example JAX-RS Resource
----
@Path("/gifts")
public class GiftResource {
    @Inject
    EntityManager entityManager;
    @Inject
    EntityViewManager entityViewManager;
    @Inject
    SantaClausService santaClausService;

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Transactional
    public Response createGift(GiftUpdateView view) {
        entityViewManager.save(entityManager, view);
        return Response.created(URI.create("/gifts/" + view.getId())).build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<GiftView> getGifts() {
        return santaClausService.findAllGifts();
    }

    @PUT
    @Path("{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Transactional
    public GiftView updateGift(@EntityViewId("id") GiftUpdateView view) {
        evm.save(em, view);
        return evm.find(em, GiftView.class, view.getId());
    }

    @Path("{id"})
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public GiftView getGift(@PathParam("id") Long id) {
        return return entityViewManager.find(entityManager, GiftView.class, view.getId());
    }
}
----

[[blaze-persistence-configuration-properties]]
== Blaze-Persistence configuration properties

There are various optional properties useful to refine your `EntityViewManager` and `CriteriaBuilderFactory` or guide guesses of Quarkus.

There are no required properties, as long as the Hibernate ORM extension is configured properly.

When no property is set, the Blaze-Persistence defaults apply.

The configuration properties listed here allow you to override such defaults, and customize and tune various aspects.

include::quarkus-blaze-persistence.adoc[opts=optional, leveloffset=+2]

== Limitations

Apache Derby::
Blaze-Persistence currently does not come with support for Apache Derby.
This limitation could be lifted in the future, if there's a compelling need for it and if someone contributes it.
