## Entities

### Quick overview

POJO annotated with [@Entity], must expose a no-arg constructor.

* class-level annotations:
  * [@NamingStrategy]
  * [@CqlName]
  * [@HierarchyScanStrategy]
* field/method-level annotations:
  * [@PartitionKey], [@ClusteringColumn]
  * [@Computed]
  * [@Transient]
  * [@CqlName]
* can inherit annotated fields/methods and [@NamingStrategy]. Only use [@Entity] on concrete
  classes.

-----

An entity is a Java class that will be mapped to a Cassandra table or [UDT](../../core/udts).
Entities are used as arguments or return types of [DAO](../daos/) methods; they can also be nested
inside other entities (to map UDT columns).

In order to be detected by the mapper, the class must be annotated with [@Entity]:

```java
@Entity
public class Product {
  @PartitionKey private UUID productId;
  private String description;
  
  public UUID getProductId() { return productId; }
  public void setProductId(UUID productId) { this.productId = productId; }
  public String getDescription() { return description; }
  public void setDescription(String description) { this.description = description; }
}
```

Each entity property will be mapped to a CQL column. In order to detect a property:

* there **must** be a getter method that follows the usual naming convention (e.g. `getDescription`)
  and has no parameters. The name of the property is obtained by removing the "get" prefix and
  decapitalizing (`description`), and the type of the property is the return type of the getter.
* there **must** be a matching setter method (`setDescription`), with a single parameter that has
  the same type as the property (the return type does not matter).

There *may* also be a matching field (`description`) that has the same type as the property, but
this is not mandatory: a property can have only a getter and a setter (for example if the value is
computed, or the field has a different name, or is nested into another field, etc.)
  
The class must expose a no-arg constructor that is at least package-private.

### Naming strategy

The mapper infers the database schema from your Java model: the entity class's name is converted
into a table name, and the property names into column names.

You can control the details of this conversion by annotating your entity class with
[@NamingStrategy].

#### Naming conventions

The simplest strategy is to use one of the mapper's built-in conventions: 

```java
import static com.datastax.oss.driver.api.mapper.entity.naming.NamingConvention.UPPER_SNAKE_CASE;

@Entity
@NamingStrategy(convention = UPPER_SNAKE_CASE)
public class Product {
  @PartitionKey private UUID productId;
  ...
}
```

Conventions convert names according to pre-defined rules. For example, with the `UPPER_SNAKE_CASE`
convention used above, the mapper expects the following schema:

```
CREATE TABLE "PRODUCT"("PRODUCT_ID" int primary key ...)
```

For the list of all available conventions, look at the enum constants in [NamingConvention].

If you don't annotate your class with [@NamingStrategy], the mapper defaults to the
`SNAKE_CASE_INSENSITIVE` convention.

#### User-provided name converter

If none of the built-in conventions work for you, you can provide your own conversion logic by
implementing [NameConverter]:

```java
public class MyNameConverter implements NameConverter {
  @Override
  public String toCassandraName(String javaName) {
    ... // implement your logic here
  }
}
```

Then pass your converter class to the annotation:

```java
@Entity
@NamingStrategy(customConverterClass = MyNameConverter.class)
public class Product {
  ...
}
```

The mapper will use reflection to build an instance of the converter; it needs to expose a public
no-arg constructor.

Note that, unlike built-in conventions, the mapper processor cannot invoke your converter at compile
time and use the converted names directly in generated code. Instead, the generated code will invoke
the converter at runtime (that is, every time you run a query). If you want to squeeze the last bit
of performance from the mapper, we recommend sticking to conventions.

#### User-provided names

Finally, you can override the CQL name manually with the [@CqlName] annotation:

```java
@PartitionKey
@CqlName("id")
private UUID productId;
```

It works both on entity properties, and on the entity class itself.

This takes precedence over the entity-level naming strategy, so it's convenient if almost all of
your schema follows a convention, but you need exceptions for a few columns.

### Property annotations

Properties can be annotated to configure various aspects of the mapping. The annotation can be
either on the field, or on the getter (if both are specified, the mapper processor issues a
compile-time warning, and the field annotation will be ignored).

#### Primary key columns

If the entity maps to a table, properties that map to partition key columns must be annotated with
[@PartitionKey]:

```java
// CREATE TABLE sales(countryCode text, areaCode text, sales int,
//                    PRIMARY KEY((countryCode, areaCode)));

@PartitionKey(1)
private String countryCode;
@PartitionKey(2)
private String areaCode;
```

If the partition key is composite, the annotation's integer value indicates the position of each
property in the key. Note that any values can be used, but for clarity it's probably a good idea to
use consecutive integers starting at 0 or 1.

Similarly, properties that map to clustering columns must be annotated with [@ClusteringColumn]: 

```java
// CREATE TABLE sensor_reading(id uuid, year int, month int, day int, value double,
//                             PRIMARY KEY(id, year, month, day));
@PartitionKey
private UUID id;
@ClusteringColumn(1)
private int year;
@ClusteringColumn(2)
private int month;
@ClusteringColumn(3)
private int day;
```

This information is used by some of the DAO method annotations; for example,
[@Select](../daos/select/)'s default behavior is to generate a selection by primary key.

#### Computed properties

Annotating an entity property with [@Computed] indicates that when retrieving data with the mapper
this property should be set to the result of a computation on the Cassandra side, typically a
function call:

```java
private int v;

@Computed("writetime(v)")
private long writetime;
```

The CQL return type of the formula must match the type of the property, otherwise an exception
will be thrown.

[@Computed] does not support case-sensitivity. If the expression contains case-sensitive column
or function names, you'll have to escape them:

```java
@Computed("\"myFunction\"(\"myColumn\")")
private int f;
```

[@Computed] fields are only used for select-based queries, so they will not be considered for
[@Update] or [@Insert] operations.

Also note that like all other properties, the expected name in a query result for a [@Computed]
property is based on the property name and the employed [@NamingStrategy](#naming-strategy). You may
override this behavior using [@CqlName](#user-provided-names).

Mapping computed results to property names is accomplished using [aliases].  If you wish to use
entities with [@Computed] properties with [@GetEntity] or [@Query]-annotated dao methods, you
must also do the same:

```java
@Entity
class MyEntity {
  @PartitionKey private int k;

  private int v;

  @Computed("ttl(v)")
  private int myTtl;

  @Computed("writetime(v)")
  @CqlName("ts")
  private long writetime;
}
```

would expect a [@Query] such as:

```java
@Dao
class MyDao {
  @Query("select k, v, ttl(v) as my_ttl, writetime(v) as ts from ${qualifiedTableId} where k=:id")
  MyEntity findById(int id);
}
```

#### Transient properties

In some cases, one may opt to exclude properties defined on an entity from being considered
by the mapper.  In this case, simply annotate these properties with [@Transient]:

```java
@Transient
private int notAColumn;
```

In addition, one may specify transient property names at the entity level by leveraging the
[@TransientProperties] annotation:

```java
@TransientProperties({"notAColumn", "x"})
@Entity
public class Product {
  @PartitionKey private UUID id;
  private String description;
  // these columns are not included because their names are specified in @TransientProperties
  private int notAColumn;
  private int x;
}
```

Finally, any field including the `transient` keyword modifier will also be considered transient,
i.e.:

```java
private transient int notAColumn;
```

#### Custom column name

Override the CQL name manually with [@CqlName], see [User-provided names](#user-provided-names)
above.

### Default keyspace

You can specify a default keyspace to use when doing operations on a given entity:

```java
@Entity(defaultKeyspace = "inventory")
public class Product {
  //....
}
```

This will be used when you build a DAO without an explicit keyspace parameter:

```java
@Mapper
public interface InventoryMapper {
  @DaoFactory
  ProductDao productDao();

  @DaoFactory
  ProductDao productDao(@DaoKeyspace String keyspace);
}

ProductDao productDao = mapper.productDao();
productDao.insert(product); // inserts into inventory.product

ProductDao productDaoTest = mapper.productDao("test");
productDaoTest.insert(product); // inserts into test.product
```

The default keyspace optional: if it is not specified, and you build a DAO without a keyspace, then
the session **must** have a default keyspace, otherwise an error will be thrown:

```java
@Entity
public class Product { ... }

CqlSession session = CqlSession.builder()
    .withKeyspace("default_ks")
    .build();
InventoryMapper mapper = new InventoryMapperBuilder(session).build();

ProductDao productDao = mapper.productDao();
productDao.insert(product); // inserts into default_ks.product
```

If you want the name to be case-sensitive, it must be enclosed in double-quotes, for example:

```java
@Entity(defaultKeyspace = "\"defaultKs\"")
```

### Inheritance

When mapping an entity class or a UDT class, the mapper will transparently scan superclasses and
parent interfaces for properties and annotations, thus enabling polymorphic mapping of one class
hierarchy into different CQL tables or UDTs.

Each concrete class must be annotated with [@Entity] and abstract classes and interfaces must not
use this annotation.

Here is an example of a polymorphic mapping:

```java
@Entity
static class Point2D {
  private int x;
  private int y;

  @CqlName("\"X\"")
  public int getX() { return x; }

  public void setX(int x) { this.x = x; }

  @CqlName("\"Y\"")
  public int getY() { return y; }

  public void setY(int y) { this.y = y; }
}

@Entity
static class Point3D extends Point2D {
  private int z;

  @CqlName("\"Z\"")
  public int getZ() { return z; }

  public void setZ(int z) {  this.z = z; }
}

abstract static class Shape {
  @PartitionKey // annotated field on superclass; annotation will get inherited in all subclasses
  protected UUID id;

  public abstract UUID getId();

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

@CqlName("rectangles")
@Entity
static class Rectangle extends Shape {
  private Point2D bottomLeft;
  private Point2D topRight;

  @CqlName("rect_id")
  @Override
  public UUID getId() { return id; }

  public Point2D getBottomLeft() { return bottomLeft; }

  public void setBottomLeft(Point2D bottomLeft) { this.bottomLeft = bottomLeft; }

  public Point2D getTopRight() { return topRight; }

  public void setTopRight(Point2D topRight) { this.topRight = topRight; }

  public double getWidth() { return Math.abs(topRight.getX() - bottomLeft.getX()); }

  public double getHeight() { return Math.abs(topRight.getY() - bottomLeft.getY()); }
}

@CqlName("circles")
@Entity
static class Circle extends Shape {
  @CqlName("center2d")
  protected Point2D center;

  protected double radius;

  @Override
  @CqlName("circle_id")
  public UUID getId() { return id; }

  public double getRadius() { return this.radius; }

  public Circle setRadius(double radius) {
    this.radius = radius;
    return this;
  }

  public Point2D getCenter() { return center; }

  public void setCenter(Point2D center) { this.center = center; }
}

@CqlName("spheres")
@Entity
static class Sphere extends Circle {

  @CqlName("sphere_id")
  @Override
  public UUID getId() { return id; }

  // overrides field annotation in Circle,
  // note that the property type is narrowed down to Point3D
  @CqlName("center3d")
  @Override
  public Point3D getCenter() { return (Point3D) center; }

  @Override
  public void setCenter(Point2D center) {
    assert center instanceof Point3D;
    this.center = center;
  }

  // overridden builder-style setter
  @Override
  public Sphere setRadius(double radius) {
    super.setRadius(radius);
    return this;
  }
}
```

The generated entity code should map to the following schema:

```
CREATE TYPE point2d ("X" int, "Y" int)
CREATE TYPE point3d ("X" int, "Y" int, "Z" int)
CREATE TABLE rectangles (rect_id uuid PRIMARY KEY, bottom_left frozen<point2d>, top_right frozen<point2d>)
CREATE TABLE circles (circle_id uuid PRIMARY KEY, center2d frozen<point2d>, radius double)
CREATE TABLE spheres (sphere_id uuid PRIMARY KEY, center3d frozen<point3d>, radius double)
```

Annotation priority is driven by proximity to the [@Entity] class. For example, in the code above 
the use of `@CqlName("sphere_id")` on `Sphere.getId()` overrides the annotation
`@CqlName("circle_id")` on `Circle.getId()` for the `Sphere` entity.

Annotations declared on classes are given priority over annotations declared by interfaces 
the same level.

To control how the class hierarchy is scanned, annotate classes with [@HierarchyScanStrategy].

[@ClusteringColumn]:    https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/ClusteringColumn.html
[@CqlName]:             https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/CqlName.html
[@Dao]:                 https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Dao.html
[@Entity]:              https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Entity.html
[NameConverter]:        https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/entity/naming/NameConverter.html
[NamingConvention]:     https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/entity/naming/NamingConvention.html
[@NamingStrategy]:      https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/NamingStrategy.html
[@PartitionKey]:        https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/PartitionKey.html
[@Computed]:            https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Computed.html
[@Select]:              https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Select.html
[@Insert]:              https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Insert.html
[@Update]:              https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Update.html
[@GetEntity]:           https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/GetEntity.html
[@Query]:               https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Query.html
[aliases]:              http://cassandra.apache.org/doc/latest/cql/dml.html?#aliases
[@Transient]:           https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/Transient.html
[@TransientProperties]: https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/TransientProperties.html
[@HierarchyScanStrategy]: https://docs.datastax.com/en/drivers/java/4.4/com/datastax/oss/driver/api/mapper/annotations/HierarchyScanStrategy.html
