= Entities (JPA)

:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:


If the xref:pjpa:ROOT:about.adoc[JPA/EclipseLink] object store is to be used, then the domain entities should be annotated using JPA annotations.

This section shows a simple example.
See the xref:pjpa:ROOT:about.adoc[JPA/Eclipselink object store] documentation for further information on annotating domain entities.


== Class definition

For the domain class itself, this will be the `@javax.persistence.Entity` annotation and probably the `@javax.persistence.Table` annotation, as well as others to define indices and queries.


[source,java]
----
@javax.persistence.Entity                                               // <.>
@javax.persistence.Table(
    schema= "simple"                                                    // <.>
    // ...
)
@EntityListeners(CausewayEntityListener.class)                          // <.>
@DomainObject(                                                          // <.>
        logicalTypeName = "simple.SimpleObject"
)
public class SimpleObject {

    @javax.persistence.Id                                               // <.>
    @javax.persistence.GeneratedValue(strategy = GenerationType.AUTO)   // <3>
    @javax.persistence.Column(name = "id", nullable = false)            // <.>
    private Long id;

    @javax.persistence.Version                                          // <.>
    @javax.persistence.Column(name = "version", nullable = false)       // <5>
    @PropertyLayout(fieldSetId = "metadata", sequence = "999")
    @Getter @Setter
    private long version;

    //...
}
----

<.> The `@Entity` annotation indicates that this is an entity to EclipseLink.
<.> Specifies the RDBMS database schema for this entity.
It's recommended that the schema corresponds to the module in which the entity resides.
The table will default to the entity name if omitted.
<.> Required boilerplate that allows Causeway to inject domain services into the entity when retrieved from the database
<.> The `@DomainObject` annotation identifies the domain object to Apache Causeway (not EclipseLink).
It isn't necessary to include this annotation -- at least, not for entities -- but it is nevertheless recommended.
In particular, its strongly recommended that the `logicalTypeName` (which acts like an alias to the concrete domain class) is specified; note that it corresponds to the schema/table for EcilpseLink's `@Table` annotation.
<.> Specified the primary key, indicating that the database will assign the key, for example using an identity column or a sequence.
<.> Indicates the column name (though this would be inferred) and nullability (such a primary keys should not be nullable).
<.> The `@Version` annotation is useful for optimistic locking; the strategy indicates what to store in the `version` column.


== Scalar Properties

All domain entities will have some sort of mandatory key properties.
Additional annotations are also required to define their scalar properties and relationships to other entities.

The example below is a very simple case, where the entity is identified by a `name` property.
This is often used in database unique indices, and in the `toString()` implementation:

[source,java]
----
import javax.persistence.Column;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.ToString.Include;

@javax.persistence.Table(
    schema= SimpleModule.SCHEMA,
    uniqueConstraints = {
        @UniqueConstraint(name = "SimpleObject__name__UNQ",
                          columnNames = {"name"})                   // <.>
    }
)
public class SimpleObject
             implements Comparable<SimpleObject> {                  // <.>

    // ...
    public SimpleObject(String name) {
        setName(name);
    }

    @Column(allowsNull="false", length=50)                          // <.>
    @Getter @Setter                                                 // <.>
    @ToString.Include                                               // <.>
    private String name;

    private final static Comparator<SimpleObject> comparator =
            Comparator.comparing(SimpleObject::getName);

    @Override
    public int compareTo(final SimpleObject other) {
        return comparator.compare(this, other);                     // <.>
    }
}
----
<.> EclipseLink will automatically add a unique index to the primary surrogate id (discussed above), but additional alternative keys can be defined using the `@Unique` annotation.
In the example above, the "name" property is assumed to be unique.
<.> Although not required, we strongly recommend that all entities are naturally `Comparable`.
This then allows parent/child relationships to be defined using ``SortedSet``s; RDBMS after all are set-oriented.
<.> Chances are that some of the properties of the entity will be mandatory, for example any properties that represent an alternate unique key to the entity.
The `@Column` annotation specifies the length of the column in the RDBMS, and whether it is mandatory.
+
Given there is a unique index on `name`, we want this to be mandatory.
+
We can also represent this using a constructor that defines these mandatory properties.
The ORM will create a no-arg constructor to allow domain entity to be rehydrated from the database at runtime (it then sets all state reflectively).

<.> Use Lombok to generate the getters and setters for the `name` property itself.
<.> Use Lombok to create a `toString()` implementation that includes the value of `name` property.

<.> Use `java.util.Comparator#comparing()` to implement `Comparable` interface.


== Queries

When using JPA, it's also common for domain entities to have queries annotated on them.
These are used by repository domain services to query for instances of the entity:

[source,java]
----
...
@javax.persistence.NamedQueries({
        @javax.persistence.NamedQuery(                                  // <.>
                name = "findByNameLike",                                // <.>
                query = "SELECT so " +                                  // <.>
                        "FROM SimpleObject so " +
                        "WHERE so.name LIKE :name"
        )
})

@javax.jdo.annotations.Queries({
    @javax.jdo.annotations.Query(                                     // <.>
      name = "findByName",                                            // <.>
      value = "SELECT "                                               // <.>
            + "FROM domainapp.modules.simple.dom.impl.SimpleObject "  // <.>
            + "WHERE name.indexOf(:name) >= 0 ")                      // <.>
})
...
public class SimpleObject { /* ... */ }
----
<.> There may be several `@NamedQuery` annotations, nested within a `@NamedQueries` annotation) defines queries using JPAQL.
<.> Defines the name of the query.
<.> The definition of the query, using JPAQL syntax.

To actually use the above definition, the framework provides the xref:refguide:applib:index/services/repository/RepositoryService.adoc[RepositoryService].
This is a generic repository for any domain class.

The corresponding repository method for the above query is:

[source,java]
----
public List<SimpleObject> findByName(String name) {
    return repositoryService.allMatches(            // <.>
            Query.named(SimpleObject.class,         // <.>
                        "findByNameLike")           // <.>
                   .withParameter("name", name)     // <.>
            );
}

@Inject RepositoryService repositoryService;
----
<.> find all instances that match the query
<.> Specifies the class that is annotated with `@NamedQuery`
<.> Corresponds to the `@NamedQuery#name` attribute
<.> Corresponds to the `:name` parameter in the query JDOQL string




