Entities
The basic building block of FeGen's and Spring's data model are entities.
Those are classes annotated with javax.persistence.Entity
for which a database table will be created where instances of those classes can be stored together with their fields.
For an entity class to work with FeGen, it needs to meet the following criteria:
- They must be located in the package specified by
scanPkg
- or
entityPkg
if that configuration key exists, see Configuration Options
- or
- They must have an
@Entity
annotation - They have an
id
field of typelong
- That field is annotated with
@Id
and@GeneratedValue
- That field is annotated with
- Other fields are annotated with a
@Column
annotation specifyingnullable
as true or false (even in Kotlin)@Notnull
and@Nullable
from Spring validation may be used instead
- They have a base projection
The last one is important since there are certain scenarios in which entities returned by the backend will not have certain properties that are required by the code generated by FeGen.
Base projection
A base projection is necessary for an entity to be correctly returned when using FeGen to request it in a client. It is an interface definition that is nested within the entity class and meets the following criteria:
- It is annotated with
@Projection
- The
name
property of its@Projection
annotation must be"baseProjection"
- The
types
property of the annotation contains only the class of the entity for which the interface is a projection - It must include a getter for all fields whose types are not entities nor projections including the
id
field.
Java
An example entity in Java may look like this:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.springframework.data.rest.core.config.Projection;
import org.springframework.lang.Nullable;
@Entity
public class SomeEntity {
@Id
@GeneratedValue
public long id;
@Column(nullable = false)
public String nonNullableField;
@Nullable
public String nullableField;
private long value;
public long getValue() {
return value;
}
public void setValue(long value) {
this.value = value;
}
private boolean b;
public boolean isB() {
return b;
}
public void setB(boolean b) {
this.b = b;
}
@Projection(name = "baseProjection", types = {SomeEntity.class})
interface BaseProjection {
long getId();
String getNonNullableField();
String getNullableField();
long getValue();
boolean isB();
}
}
As you can see, there are two options of defining entity columns.
You can either just use a single field or specify a getter for your field (like it was done for the value
and b
columns).
Since Spring and FeGen can conclude from the name and signature of the function that getValue
is a getter for value
, only one column named value
is created.
If you wanted to annotate the value
or b
column, you could do so on the getter or the field.
Since the value
and b
columns have primitive types, you do not need to specify their nullability.
Kotlin
The entity from the Java example may look like this if written in Kotlin:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.springframework.lang.Nullable;
@Entity
class SomeEntity {
@Id
@GeneratedValue
var id: Long = -1
@Column(nullable = false)
lateinit var nonNullableField: String
@Nullable
var nullableField: String? = null
var value: Long = 0
var b: Boolean = false
@Projection(name = "baseProjection", types = [SomeEntity::class])
interface BaseProjection {
val id: Long
val firstName: String
val lastName: String
val number: String?
}
}
In Kotlin, it is best to define columns using the var
keyword.
If the type of your column is primitive, you need to initialize it like it is the case with id
and value
.
Otherwise, you can use the lateinit
modifier to avoid having to initialize a property that will often be overwritten by the contents of the database anyway.
You still have to specify nullability for non-primitive properties, even though Kotlin has a notion of nullability in its types, because Spring will ignore them.
For the base projection you can just use val
s as they will be recognized by Spring in the same way as getters are.
Repositories
Without a repository, you will not be able to perform CRUD operations on your entity from the code generated by FeGen.
The repository for your entity must be an interface that meets the following criteria:
- It is located in the package specified by
scanPkg
- or
repositoryPkg
if that configuration key exists, see Configuration Options
- or
- It extends
JpaRepository
with your entity andLong
as type parameters
In Java, it will look like this:
public interface SomeEntityRepository extends JpaRepository<SomeEntity, Long> {}
In Kotlin, it will look like this:
interface SomeEntityRepository: JpaRepository<SomeEntity, Long>
Frontend
To see how you can access your entities from your frontend, take a look at the Typescript or Kotlin page depending on what client language you are generating code for.