Cassandra的mapped类定义

Creating a table entity

A table entity is a class that will be mapped to a table in Cassandra. It is annotated with @Table:

@Table(keyspace = "ks", name = "users",
       readConsistency = "QUORUM",
       writeConsistency = "QUORUM",
       caseSensitiveKeyspace = false,
       caseSensitiveTable = false)
public class User {
    @PartitionKey
    @Column(name = "user_id")
    private UUID userId;
    private String name;
    // ... constructors / getters / setters
}

@Table takes the following options:

  • keyspace: the keyspace for the table.
  • name: the name of the table in the database.
  • caseSensitiveKeyspace: whether the keyspace name is case-sensitive.
  • caseSensitiveTable: whether the table name is case-sensitive.
  • readConsistency: the consistency level that will be used on each get operation in the mapper. (if unspecified, it defaults to the cluster-wide setting)
  • writeConsistency: the consistency level that will be used on each save, or delete operation in the mapper. (if unspecified, it defaults to the cluster-wide setting)

 

 

 

Mapping table columns 

@Table(name = "users")
public class User {

    // annotation on a field
    @PartitionKey
    private UUID id;

    public UUID getId() {
        return id;
    }

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

}
@Table(name = "users")
public class User {

    private UUID id;

    // annotation on a getter method
    @PartitionKey
    public UUID getId() {
        return id;
    }

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

}

注解可以加在域(字段)上,也可以加在方法上,项目最好始终用同一种方案.

 

注解域较少冗余

注解方法,在多态数据模型则更灵活

如果同时注解了域和方法,则使用方法的注解.

 

 

 

Cassandra的Column和Bean的字段

column会与field的相同名字(大小写不敏感)进行映射

若想给colum取一个不同的field名字,则可以注解

// column name does not match field name
@Column(name = "user_name")
private String userName;

若想要大小写敏感,可以

// column name is case-sensitive
@Column(caseSensitive = true)
private String userName;

 

Primary key fields

@PartitionKey标签的使用

CREATE TABLE sales(countryCode text, areaCode text, sales int,
                   PRIMARY KEY((countryCode, areaCode)));
@PartitionKey(0)
private String countryCode;
@PartitionKey(1)
private String areaCode;

建表语句的多primary key的顺序在bean中的表现如代码所示,从0开始标号

Computed fields

@Computed可以在Cassandra端的计算结果的属性上使用.可以是Cassandra的函数或者自定义的方法.

@Computed("ttl(name)")
Integer ttl;

CQL返回的类型要与name匹配

Transient properties

默认情况下,映射器会试图把所有字段和bean属性映射到表的列上,

注解@Transaction可以组织这一行为

 

 

Mapping User Types

User Defined Types can also be mapped by using @UDT:

CREATE TYPE address (street text, zip_code int);
@UDT(keyspace = "ks", name = "address")
class Address {
    private String street;
    @Field(name = "zip_code")
    private int zipCode;
    // ... constructors / getters / setters
}

所以什么是Types呢?

一个table可以有UDT 列,mapper湖自动映射到相应类,二者结合如下:

CREATE TABLE company (company_id uuid PRIMARY KEY, name text, address address);

public class Company {
    @PartitionKey
    @Column(name = "company_id")
    private UUID companyId;
    private String name;
    private Address address;
}

UDTs可以嵌套到集合,或者其他UDTs中

 

Mapping collections

Java collections will be automatically mapped into corresponding Cassandra types. As in Cassandra, collections can contain all native types and all user types previously defined is the database.

// Will be mapped as a 'list<text>'
private List<String> stringList;

// Will be mapped as a 'frozen<list<text>>'
@Frozen
private List<String> frozenStringList;

// Will be mapped as 'map<frozen<address>, frozen<list<text>>>'
@FrozenKey
@FrozenValue
private Map<Address, List<String>> frozenKeyValueMap;

// Will be mapped as 'map<text, frozen<list<address>>>'
@FrozenValue
private Map<String, List<Address>> frozenValueMap;

@Frozen标签意义还不明确 indicate whether they are frozen

Polymorphism support

实体类或UDT类,映射器会扫描父类父接口的注解,因此一个类有多层次(多态),会映射到不同CQL或者UDTs

一个类必须只对应一个table或或者UTD,并且要用@Table or @UDT注解.  这类似于通常通流行的SQL映射框架(如Hibernate)的"table per concrete class"策略.

Here is an example of a polymorphic mapping:

CREATE TYPE point2d (x int, y int);
CREATE TYPE point3d (x int, y int, z int);
CREATE TABLE rectangles (id uuid PRIMARY KEY, bottom_left frozen<point2d>, top_right frozen<point2d>);
CREATE TABLE spheres (id uuid PRIMARY KEY, center frozen<point3d>, radius double);

 

@UDT(name = "point2d")
public class Point2D {
    public int x;
    public int y;
}

@UDT(name = "point3d")
public class Point3D extends Point2D {
    public int z;
}

public interface Shape2D {

    @Transient
    double getArea();

}

public interface Shape3D {

    @Transient
    double getVolume();

}

public abstract class Shape {

    private UUID id;

    @PartitionKey
    public UUID getId() {
        return id;
    }

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

}

@Table(name = "rectangles")
public class Rectangle extends Shape implements Shape2D {

    private Point2D bottomLeft;
    private Point2D topRight;

    @Column(name = "bottom_left")
    @Frozen
    public Point2D getBottomLeft() {
        return bottomLeft;
    }

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

    @Column(name = "top_right")
    @Frozen
    public Point2D getTopRight() {
        return topRight;
    }

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

    @Transient
    public double getWidth() {
        return Math.abs(topRight.x - bottomLeft.x);
    }

    @Transient
    public double getHeight() {
        return Math.abs(topRight.y - bottomLeft.y);
    }

    @Override
    public double getArea() {
        return getWidth() * getHeight();
    }

}

@Table(name = "spheres")
public class Sphere extends Shape implements Shape3D {

    private Point3D center;
    private double radius;

    @Frozen
    public Point3D getCenter() {
        return center;
    }

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

    public double getRadius() {
        return radius;
    }

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

    @Override
    public double getVolume() {
        return 4d / 3d * Math.PI * Math.pow(getRadius(), 3);
    }

}

One powerful advantage of annotating getter methods is that annotations are inherited from overridden methods in superclasses and superinterfaces; in other words, if a getter method is overridden in a subclass, annotations in both method declarations will get merged together. If duplicated annotations are found during this merge process, the overriding method's annotations will take precedence over the overridden's.

 

posted on 2017-01-11 11:43  天娱邪神  阅读(781)  评论(0编辑  收藏  举报