-
Notifications
You must be signed in to change notification settings - Fork 353
Entity persister
Astyanax provides entity persister APIs that is similar to Java Persistence API (JPA). Please check out "com.netflix.astyanax.entitystore" package.
- we uses annotations from javax.persistence package
- entity class must be annotated with @Entity
- field with @Id annotation will be written as rowKey in cassandra data model. If the same field can also have @Column annotation, then it will also be written as a column redundantly.
- column name cannot contain dot (.) char, which is reserved separator for nested structure
- column name will be normalized to lower cases when writing to cassandra. In another word, column name is case insensitive.
Here is sample code snippet from DefaultEntityManagerTest.java
final String id = "foo";
final SampleEntity origEntity = createRandomEntity(id);
final EntityManager<SampleEntity, String> entityManager =
new DefaultEntityManager.Builder<SampleEntity, String>()
.withEntityType(SampleEntity.class)
.withKeyspace(keyspace)
.withColumnFamily(CF_SAMPLE_ENTITY)
.build();
entityManager.put(origEntity);
SampleEntity getEntity = entityManager.get(id);
entityManager.delete(id);
Here are the ways to specify TTL (lower priority first)
- @TTL annotation at entity class level
@Entity
@TTL(3600) // 1 hour
public class FooEntity {
// your class definition
}
- DefaultEntityManager Builder EntityManager<FooEntity, String> entityPersister = new DefaultEntityManager.Builder<FooEntity, String>() .withEntityType(FooEntity.class) .withKeyspace(keyspace) .withColumnFamily(columnFamily) .withTTL(3600) // 1 hour .build();
@Entity
@TTL(3600) // 1 hour
public class FooEntity {
// your class definition
}
- @TTL annotation at entity method level. this the dynamic and most flexible way of deriving TTL value. e.g. you may have entities that are time dependent (e.g. flight schedules, subscriptions to services, etc.) where the TTL basically has to be bigger than the "end date" of that particular entity (which will vary per row/entity).
@Entity
public class FooEntity {
// it must be zero args and return Integer type
@TTL
public Integer getTTL() {
// your TTL calculation logic
}
}
- We support nested structure. column name will be concatenated by "." char. That's why dot char is invalid in @Column name annotation.
- Nested type must also be annotated with @Entity just like the root type. But the difference is that nested type doesn't need @Id field/annotation.
- Nesting can be any arbitrary level deep.
Here is the code snippet from SampleEntity.java. When SampleEntity is written to cassandra. There will be two columns of "bar.i" and "bar.s".
@Entity
public class SampleEntity {
@Entity
public static class Bar {
@Column(name="i")
public int i;
@Column(name="s")
public String s;
...
}
...
@Column(name="BAR")
private Bar bar;
...
}
By default (without @Serializer annotation), astyanax will automatically infer the Serializer type based on entity field's java type. Here are the following inference types supported by entity persister.
- basic java types (both primitive and wrapper): byte, short, int, long, boolean, float, double
- String, byte[], Date, UUID
If you have a field that requires custom Serializer, you can specify it with the @Serializer annotation. Here is the code snippet from SampleEntity.java
public class SampleEntity {
public static class Foo {
public int i;
public String s;
public Foo(int i, String s) {
this.i = i;
this.s = s;
}
@Override
public String toString() {
try {
JSONObject jsonObj = new JSONObject();
jsonObj.put("i", i);
jsonObj.put("s", s);
return jsonObj.toString();
} catch (JSONException e) {
throw new RuntimeException("failed to construct JSONObject for toString", e);
}
}
public static Foo fromString(String str) {
try {
JSONObject jsonObj = new JSONObject(str);
return new Foo(jsonObj.getInt("i"), jsonObj.getString("s"));
} catch (JSONException e) {
throw new RuntimeException("failed to construct JSONObject for toString", e);
}
}
...
}
public static class FooSerializer extends AbstractSerializer<Foo> {
private static final String UTF_8 = "UTF-8";
private static final Charset charset = Charset.forName(UTF_8);
private static final FooSerializer instance = new FooSerializer();
public static FooSerializer get() {
return instance;
}
@Override
public ByteBuffer toByteBuffer(Foo obj) {
if (obj == null) {
return null;
}
return ByteBuffer.wrap(obj.toString().getBytes(charset));
}
@Override
public Foo fromByteBuffer(ByteBuffer byteBuffer) {
if (byteBuffer == null) {
return null;
}
return Foo.fromString(charset.decode(byteBuffer).toString());
}
...
}
@Column(name="FOO")
@Serializer(FooSerializer.class)
private Foo foo;
...
}
A Netflix Original Production
Tech Blog | Twitter @NetflixOSS | Jobs
- Getting-Started
- Configuration
- Features
- Monitoring
- Thread Safety
- Timeouts
- Recipes
- Examples
- Javadoc
- Utilities
- Cassandra-Compatibility
- FAQ
- End-to-End Examples
- Astyanax Integration with Java Driver