Cassandra-Java(增刪查改)


驅動下載

  創建maven工程,讓maven來維護我們的jar,maven最重要的pom文件內容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.huawei</groupId>
    <artifactId>cassandra</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cassandra</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
       <dependency>
            <groupId>com.datastax.cassandra</groupId>
            <artifactId>cassandra-driver-core</artifactId>
            <version>2.1.10.3</version>
        </dependency>
    </dependencies>
</project>

Session獲取

  官方給的Quick start案例

Cluster cluster = null;
        try {
            cluster = Cluster.builder()                                                    // (1)
                    .addContactPoint("127.0.0.1")                                 // cassandra服務器ip
                    .withCredentials("admin", "admin")                                     // 若沒有啟用賬號認證,此處可以去掉
                    .build();
            Session session = cluster.connect();                                           // (2)

            ResultSet rs = session.execute("select release_version from system.local");    // (3)
            Row row = rs.one();
            System.out.println(row.getString("release_version"));                          // (4)
        } finally {
            if (cluster != null) cluster.close();                                          // (5)
        }

  代碼中的(1) ~ (5)分別表示或者代表什么

    (1):Cluster對象是驅動程序的主入口點,它保存着真實Cassandra集群的狀態(尤其是元數據);Cluster是線程安全的,一個Cassandra集群創建一個Cluster的單例,整個應用用這一個單例即可

    (2):Session用來執行查詢的,而且它也是線程安全的,同樣也應該重復利用

    (3):利用execute來發送一個查詢到Cassandra,execute返回一個Resultset(結果集),這個結果集就是必要的列的行集合(二維表,行是滿足條件的記錄,列是我們關注的某些字段)

    (4):從row中提取數據

    (5):當任務完成后,關閉cluster,關閉cluster的同時將會關閉它創建的全部session;這一步很重要,它會釋放潛在的資源(TCP連接、線程池等),在真實的應用中,我們應該在應用關閉(或應用卸載)的時候關閉cluster

    有jdbc開發的經驗,就會發現,上述代碼似曾相識,上述代碼中的session就相當於jdbc中的connection,是整個數據庫操作的基礎,那么我們將session的獲取單獨抽出來

 
package com.huawei.cassandra.factory;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;

public class SessionRepository
{
    private static Session instance = null;
    private static Cluster cluster = null;
    private static Lock lock = new ReentrantLock();
    
    private SessionRepository(){}
    
    public static Session getSession()
    {
        if (null == instance)
        {
            try
            {
                lock.lock();
                
                if (null == instance)
                {
                    cluster = Cluster.builder()       
                            .addContactPoint("127.0.0.1")                
                            .withCredentials("admin", "admin")              
                            .build();
                    instance = cluster.connect();
                    // 也可以針對一個特定的keyspace獲取一個session
                    // instance = cluster.connect("mycas");
                }
            }
            finally
            {
                lock.unlock();
            }
        }
        return instance;
    }
    
    public static void close()
    {
        if (null == cluster)
        {
            try
            {
                lock.lock();
                
                if (null == cluster)
                {
                    cluster.close();
                }
            }
            finally
            {
                lock.unlock();
            }
        }
    }
}

    拿到session了,那么請隨意操作Cassandra吧!

cassandra基本操作

  創建表

    在mycas下創建表student

use mycas;
create table student(
    id int,
    address text,
    name text,
    age int,
    height int,
    primary key(id,address,name)
);

insert into student(id,address,name,age,height) values(1,'guangdong','lixiao',32,172);

  session直接執行cql

    和jdbc類似,關鍵是cql的拼接,下例是插入一條記錄,刪、改、查和這類似,不一一列舉了

    // 字符串注意單引號'
        String cql = "insert into mycas.student(id,address,name,age,height) values(" 
                + student.getId() + ",'" + student.getAddress() + "','" + student.getName()
                + "'," + student.getAge() + "," + student.getHeight() + ");";
        System.out.println(cql);
        session.execute(cql);

  Querybuilder

    利用Querybuilder可以減輕cql的拼接,sql語句的拼接由驅動完成

    查詢一個student:

    @Override
    public Student getStudentByKeys(int id, String address, String name)
    {
        Student student = null;
        ResultSet rs = session.execute(
                QueryBuilder.select("id", "address", "name", "age", "height")
                .from("mycas", "student")
                .where(QueryBuilder.eq("id", id))
                .and(QueryBuilder.eq("address", address))
                .and(QueryBuilder.eq("name", name)));
        Iterator<Row> rsIterator = rs.iterator();
        if (rsIterator.hasNext())
        {
            Row row = rsIterator.next();
            student = new Student();
            student.setAddress(row.getString("address"));
            student.setAge(row.getInt("age"));
            student.setHeight(row.getInt("height"));
            student.setId(row.getInt("id"));
            student.setName(row.getString("name"));
        }
        return student;
    }

    保存一個student:

  @Override
    public void saveStudent(Student student)
    {
        session.execute(
                QueryBuilder.insertInto("mycas", "student")
                .values(new String[]{"id", "address", "name", "age", "height"},
                        new Object[]{student.getId(), student.getAddress(), 
                            student.getName(), student.getAge(), student.getHeight()}));
    }

    修改一個student:

@Override
    public void updateStudent(Student student)
    {
        session.execute(
                QueryBuilder.update("mycas", "student")
                .with(QueryBuilder.set("age", student.getAge()))
                .and(QueryBuilder.set("height", student.getHeight()))
                .where(QueryBuilder.eq("id", student.getId()))
                .and(QueryBuilder.eq("address", student.getAddress()))
                .and(QueryBuilder.eq("name", student.getName())));
    }

    刪除一個student:

@Override
    public void removeStudent(int id, String address, String name)
    {
        session.execute(QueryBuilder.delete()
                .from("mycas", "student")
                .where(QueryBuilder.eq("id", id))
                .and(QueryBuilder.eq("address", address))
                .and(QueryBuilder.eq("name", name)));
    }

  注意:驅動版本不同,Querybuilder的用法有些許不同,有些版本的某些方法變成非靜態的了!

  占位符

    cassandra也有類似jdbc那樣使用預編譯占位符

    http://docs.datastax.com/en/developer/java-driver/3.0/manual/statements/prepared/

    預編譯的原理是怎樣的了,上面的鏈接是驅動官方的解釋,我來談談我的理解

    當我們預編譯statement的時候,Cassandra會解析query語句,緩存解析的結果並返回一個唯一的標志(PreparedStatement對象保持着這個標志的內部引用,就相當於通過標志可以獲取到query語句預編譯后的內容):

     當你綁定並且執行預編譯statement的時候,驅動只會發送這個標志,那么Cassandra就會跳過解析query語句的過程:

    所以,我們應該保證query語句只應該被預編譯一次,緩存PreparedStatement 到我們的應用中(PreparedStatement 是線程安全的);如果我們對同一個query語句預編譯了多次,那么驅動會打印警告日志;如果一個query語句只執行一次,那么預編譯不會提供性能上的提高,反而會降低性能,因為它是兩個來回(結合上面兩張圖),那么此時可以考慮用 simple statement 來代替

    和jdbc的預編譯非常類似,我們來看看實際代碼

    靜態cql

  private static final String GET_STUDENT = "select id,address,name,age,height from mycas.student where id=? and address=? and name=?;";
  private static final String SAVE_STUDENT = "insert into mycas.student(id,address,name,age,height) values(?,?,?,?,?);";
  private static final String UPDATE_STUDENT = "update mycas.student set age=?, height=? where id=? and address=? and name=?;";
  private static final String REMOVE_STUDENT = "delete from mycas.student where id=? and address=? and name=?;";

    查詢一個student

     Student student = null;
        PreparedStatement prepareStatement = session.prepare(GET_STUDENT);
        BoundStatement bindStatement = new BoundStatement(prepareStatement).bind(id, address, name);
        ResultSet rs = session.execute(bindStatement);
        Iterator<Row> rsIterator = rs.iterator();
        if (rsIterator.hasNext())
        {
            Row row = rsIterator.next();
            student = new Student();
            student.setAddress(row.getString("address"));
            student.setAge(row.getInt("age"));
            student.setHeight(row.getInt("height"));
            student.setId(row.getInt("id"));
            student.setName(row.getString("name"));
        }
        return student;

    保存一個student

        PreparedStatement prepareStatement = session.prepare(SAVE_STUDENT);
        BoundStatement bindStatement = new BoundStatement(prepareStatement)
            .bind(student.getId(), student.getAddress(), student.getName(), student.getAge(), student.getHeight());
        session.execute(bindStatement);

    修改一個student

     PreparedStatement prepareStatement = session.prepare(UPDATE_STUDENT);
        BoundStatement bindStatement = new BoundStatement(prepareStatement)
            .bind(student.getAge(), student.getHeight(), student.getId(), student.getAddress(), student.getName());
        session.execute(bindStatement);

    刪除一個student

     PreparedStatement prepareStatement = session.prepare(REMOVE_STUDENT);
        BoundStatement bindStatement = new BoundStatement(prepareStatement)
            .bind(id, address, name);
        session.execute(bindStatement);

  批量batch

public static void batch()
    {
        Session session = SessionRepository.getSession();
        BoundStatement insertBind1 = new BoundStatement(
                session.prepare("insert into mycas.student(id,address,name,age,height) values(?,?,?,?,?);"))
                       .bind(3, "guangxi", "huangfeihong", 67, 175);
        
        BoundStatement insertBind2 = new BoundStatement(
                session.prepare("insert into mycas.student(id,address,name,age,height) values(?,?,?,?,?);"))
                       .bind(4, "hunan", "youzhibing", 26, 160);
        
        BoundStatement updateBind = new BoundStatement(
                session.prepare("update mycas.student set age=?, height=? where id=? and address=? and name=?;"))
                       .bind(72, 173, 3, "guangxi", "huangfeihong");
        
        BoundStatement deleteBind = new BoundStatement(
                session.prepare("delete from mycas.student where id=? and address=? and name=?;"))
                       .bind(4, "hunan", "youzhibing");
        
        BatchStatement batchStatement = new BatchStatement();
        batchStatement.add(insertBind1);
        batchStatement.add(insertBind2);
        batchStatement.add(updateBind);
        batchStatement.add(deleteBind);
        session.execute(batchStatement);
    }

public static void batch()
    {
        Session session = SessionRepository.getSession();
        BoundStatement insertBind1 = new BoundStatement(
                session.prepare("insert into mycas.student(id,address,name,age,height) values(?,?,?,?,?);"))
                       .bind(3, "guangxi", "huangfeihong", 67, 175);
        
        BoundStatement insertBind2 = new BoundStatement(
                session.prepare("insert into mycas.student(id,address,name,age,height) values(?,?,?,?,?);"))
                       .bind(4, "hunan", "youzhibing", 26, 160);
        
        BoundStatement updateBind = new BoundStatement(
                session.prepare("update mycas.student set age=?, height=? where id=? and address=? and name=?;"))
                       .bind(72, 173, 3, "guangxi", "huangfeihong");
        
        BoundStatement deleteBind = new BoundStatement(
                session.prepare("delete from mycas.student where id=? and address=? and name=?;"))
                       .bind(4, "hunan", "youzhibing");
        
        BatchStatement batchStatement = new BatchStatement();
        batchStatement.add(insertBind1);
        batchStatement.add(insertBind2);
        batchStatement.add(updateBind);
        batchStatement.add(deleteBind);
        session.execute(batchStatement);
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM