Skip to content

Support for User Defined Types and Indexes on Collections

karthikprasad13 edited this page Oct 6, 2015 · 7 revisions

Kundera is upgraded to be compatible with Cassandra 2.1+ from 2.15.1 onwards. Cassandra 2.1+ came with a number of new features and improvements which include support for User Defined Types and creating indexes on collections. From 2.15.1 these features are now enabled in Kundera.

Why support it?

Using User-Defined Types, one can store small group of related data together with the main data, instead of using another columnfamlily, etc. For example, we can have a single field of custom type address with fields street, city and pin in it.

Set CQL version 3:

UDTs are supported only on CQL3. So, make sure you set CQL to version 3 as shown below.

    Map<String, Object> puProperties = new HashMap<String, Object>();
    puProperties.put(CassandraConstants.CQL_VERSION, CassandraConstants.CQL_VERSION_3_0);
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("cassandra_pu", puProperties);
    EntityManager em = emf.createEntityManager();

How to use UDTs?

If you have a defined type in the database, which is equivalent to:

CREATE TYPE "keyspace"."Address" (
street text,
city text,
pin text
);

In Kundera, you can register this UDT by creating a class annotated with @Embeddable annotation and defining the desired fields in it.

Example:

@Embeddable
public class Address
{
	@Column 
   	private String street;
	@Column 
   	private String city;
	@Column
   	private String pin;

  //Setters and Getters
}

Now, to use this type in your entity, define a field of this type and annotate it with @Embedded annotation.

Example:

@Entity
@Table(name="user", schema="keyspace@PU")
public class User
{

    @Id
    @Column
    private int userid;
    @Column  
    private String firstname; 
    @Embedded
    private Address address;

    //Setters and Getters
}

Equivalent columnfamily in cassandra:

CREATE TABLE "UdtTest".person_udt (
    "userid" int PRIMARY KEY,
    firstname text,
    address frozen<Address>
);

Handling data:

You can now store, retrieve data by using setters and getters of that type.

Example:

//set fields of UDT
Address address = new Address();
address.setStreet(“mystreet”);
address.setCity(“mycity”);
address.setPin(“mypin”);

User user = new User();
user.setUserid(1);
user.setFirstname(“myname”);
user.setAddress(address); //set UDT in entity
enityManager.persist(user); //persist

//similar retrieving
User user = entityManager.find(User.class, 1);
String city = user.getAddress().getCity().

##Collection of UDTs: In addition to UDT fields, Kundera also supports Collections of UDTs and it can be used by annotating the field with @ElementCollection

Example:

addresses map<text, frozen<address>>

The above field in Cassandra is equivalent to the following in mapped Java entity:

@ElementCollection
Map<String, Address> addresses;

Indexes on Collections:

To enable querying on elements in a collection, you have to declare the collection field in @IndexCollection.

Example:

@Entity
@Table(name="collection_example", schema="keyspace@PU")
@IndexCollection(columns = { @Index(“phoneNums”) }) //index on collection
public class CollectionExample
{

    @Id
    @Column
    private int userid;
    @Column  
    private String firstname; 
    @Column  
    private List<String> phoneNums; 

    //Setters and Getters
}

Limitations:

  • Querying on fields inside UDTs

PS:- Kundera, also supports Embeddables on CQL version 2 implemented using super columns. Here is the reference for more information on this.

Clone this wiki locally