JAVA AWS 根據Dynamodb增刪改查數據


前言

dynamodb是AWS的一款非關系型數據庫。適用於無需頻繁增刪改查且關聯性不強的大數據,比如某個用戶的歷史訂單信息等。

歷史訂單可能不常查詢但數據量很大,且只要有用戶ID就可以查詢出來,類似這種的可以使用非關系型數據庫。

這個例子未必恰當,僅想表達不是任何情況都要使用非關系型數據庫,每種數據庫都有其存在的意義。(曾經因為這個被坑的很慘)

進入正題:

可進入AWS官網查看Java Dynamodb的文檔,但我覺得文檔寫的過大過多,不太好找,所以自己記錄下。

在AWS控制台創建表,創建過程中要制定分區鍵和排序鍵,若未創建排序鍵無法候補,只能刪表重建。

Dynamodb無法分庫,因此表名要清楚明了。

重要::雖然我很菜,寫的也不夠好,但我不接受任何批評,本文僅供有需要的人參考及自己記錄用。

實體常用注解:映射實體和表的關系,放在getter方法上

@DynamoDBHashKey 注釋分區鍵
@DynamoDBRangeKey 注釋排序鍵
@DynamoDBAttribute 注釋普通屬性
@DynamoDBIndexHashKey 注釋二級索引分區鍵
@DynamoDBIndexRangeKey 注釋二級索引排序鍵
@DynamoDBIgnore 忽略某個對象或屬性
// 分區鍵
@DynamoDBHashKey(attributeName="user_id")
public String getUserId() {
    return userId;
}

// 排序鍵
@DynamoDBRangeKey(attributeName="event_id")
public String getEventId() {
    return eventId;
}

// 二級索引
@DynamoDBIndexHashKey(globalSecondaryIndexName= "user_name-index", attributeName= "user_name")
public String getUserName() {
    return userName;
}

// 屬性
@DynamoDBAttribute(attributeName="user_gender")
public String getUserGender() {
    return userGender;
}

// 忽略
@DynamoDBIgnore
public Student getStudent() {
    return student;
}

...

代碼實現

注意::

① withKeyConditionExpression 針對分區鍵、排序鍵的查詢條件中,不支持使用contains模糊查詢

② withFilterExpression 針對其他字段的過濾查詢條件,結合limit使用,會先查詢,后分頁,導致數據變少

因此Dynamodb無法在模糊查詢的同時進行分頁。

Service層

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.QueryResultPage;
import com.amazonaws.services.dynamodbv2.datamodeling.ScanResultPage;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TestService {

    @Autowired
    public BaseDao baseDao;

    /**
     * Student表: 分區鍵student_id、二級索引student_name等
     * Teacher表: 分區鍵teacher_id、排序鍵student_id、二級索引teacher_name等
     *
     */

    /**
     * 插入數據
     */
    public void saveDemoData() {
        Student demoInfo = new Student();
        demoInfo.setStudentId("sId1");
        demoInfo.setStudentName("sName1");

        baseDao.saveItem(demoInfo);
    }

    /**
     * 更新數據
     */
    public void updateDemoData() {
        Student demoInfo = new Student();
        demoInfo.setStudentId("sId1");
        demoInfo.setStudentName("sName1");

        baseDao.updateItem(demoInfo);
    }

    /**
     * 刪除數據
     */
    public void deleteDemoData() {
        Student demoInfo = new Student();
        demoInfo.setStudentId("sId1");
        demoInfo.setStudentName("sName1");

        baseDao.deleteItem(demoInfo);
    }

    /**
     * Query
     * 根據分區鍵查詢
     */
    public Student getQueryResult() {
        Student demoInfo = (Student) baseDao.getQueryResult(Student.class, "sId1");
        System.out.println(demoInfo);
        return demoInfo;
    }
    
    /**
     * Query
     * 根據二級索引查詢
     */
    public void getQueryIndexResult() {
        // 構建查詢數據
        Map<String, AttributeValue> vals = new HashMap<>();
        vals.put(":v_student_name", new AttributeValue().withS("sName1"));

        DynamoDBQueryExpression<Student> exp = new DynamoDBQueryExpression<Student>()
                .withKeyConditionExpression("student_name = :v_student_name") // 查詢條件
                .withIndexName("student_name-index") // 二級索引名稱
                .withExpressionAttributeValues(vals) // 查詢條件賦值
                .withConsistentRead(false); // 最終一致性,需設置成false

        QueryResultPage<Student> result = (QueryResultPage<Student>) baseDao.getQueryPageExpResult(Student.class, exp);

        System.out.println(result);
        // 總條數
        System.out.println("Result size ===>" + result.getResults().size());
        // 是否存在下一頁
        System.out.println("Last evaluated key ===>" + result.getLastEvaluatedKey());
    }
    

    /**
     * Query 查詢
     * 根據分區鍵、排序鍵查詢數據
     */
    public void getQueryExpResult() {
        Map<String, AttributeValue> vals = new HashMap<String, AttributeValue>();
        vals.put(":v_teacher_id", new AttributeValue().withS("tId1"));
        vals.put(":v_student_id",new AttributeValue().withS("sId1"));

        DynamoDBQueryExpression<Teacher> queryExpression = new DynamoDBQueryExpression<Teacher>()
            .withKeyConditionExpression("teacher_id = :v_teacher_id and student_id > :v_student_id")
            .withExpressionAttributeValues(vals);

        List<Teacher> list = baseDao.getQueryExpResult(Teacher.class, queryExpression);
        System.out.println(list);
    }
    
    /**
     * Query 分頁查詢
     * 根據二級索引查詢
     */
    public void getQueryPageExpResult() {
        // 構建查詢數據
        Map<String, AttributeValue> vals = new HashMap<>();
        vals.put(":v_teacher_name", new AttributeValue().withS("tName1"));

        DynamoDBQueryExpression<Teacher> exp = new DynamoDBQueryExpression<Teacher>()
                .withKeyConditionExpression("teacher_name = :v_teacher_name") // 查詢條件
                .withIndexName("teacher_name-index") // 二級索引名稱
                .withExpressionAttributeValues(vals) // 查詢條件賦值
                .withScanIndexForward(true)
                .withConsistentRead(false)
                .withLimit(3); // 分頁條數

        // 下一頁賦值
        Map<String, AttributeValue> startKey = new HashMap<>();
        startKey.put("teacher_id", new AttributeValue().withS("tId1"));
        startKey.put("student_id", new AttributeValue().withS("sId2"));
        exp.setExclusiveStartKey(startKey);

        QueryResultPage<Teacher> result = (QueryResultPage<Teacher>) baseDao.getQueryPageExpResult(Teacher.class, exp);

        // 返回結果
        List<Teacher> list = result.getResults();
        
        System.out.println("Result size ===>" + result.getResults().size());
        System.out.println("Last evaluated key ===>" + result.getLastEvaluatedKey());

    }

    /**
     * Scan 查詢
     */
    public void getScanList() {
        Map<String, AttributeValue> vals = new HashMap<>();
        vals.put(":v_student_address", new AttributeValue().withS("地址1"));

        // 構建查詢數據
        DynamoDBScanExpression exp = new DynamoDBScanExpression()
                .withFilterExpression("contains(student_address,:v_student_address)")
                .withExpressionAttributeValues(vals)
                .withLimit(3);

        List<Student> b = (List<Student>) baseDao.getScanResult(Student.class, exp);
    }

    /**
     * Scan分頁查詢
     */
    public void getScanPageList() {
        Map<String, AttributeValue> vals = new HashMap<>();
        vals.put(":v_student_address", new AttributeValue().withS("地址1"));

        DynamoDBScanExpression exp = new DynamoDBScanExpression()
                .withFilterExpression("contains(student_address,:v_student_address)")
                .withExpressionAttributeValues(vals)
                .withLimit(3);

         // 下一頁賦值
        Map<String, AttributeValue> startKey = new HashMap<>();
        startKey.put("student_id", new AttributeValue().withS("sId1"));
        exp.setExclusiveStartKey(startKey);

        ScanResultPage<Student> result = baseDao.getScanPageResult(Student.class, exp);

        System.out.println("Result size ===>" + result.getResults().size());
        System.out.println("Last evaluated key ===>" + result.getLastEvaluatedKey());
    }

}

 

Dao層

import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.*;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class BaseDao {

    static Regions region = Regions.CN_NORTHWEST_1;
    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
            .withRegion(region).build();
    static DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(client);
    
    /**
     * 插入數據
     */
    public void saveItem(Object clazz) {
        try {
            dynamoDBMapper.save(clazz);
        } catch (Exception e) {
            System.err.println("插入失敗:" + e.getMessage());
        }
    }
    
    /**
     * 更新數據
     */
    public void updateItem(Object clazz) {
        try {
            dynamoDBMapper.save(clazz);
        } catch (Exception e) {
            System.err.println("更新失敗:" + e.getMessage());
        }
    }
    
    /**
     * 刪除數據
     */
    public void deleteItem(Object clazz) {
        try {
            dynamoDBMapper.delete(clazz);
        } catch (Exception e) {
            System.err.println("刪除失敗:" + e.getMessage());
        }
    }
    
    /**
     * Query
     * 根據分區鍵查詢
     */
    public Object getQueryResult(Class<?> clazz, String pk) {
        return dynamoDBMapper.load(clazz, pk);
    }
    
    /**
     * Query
     * 根據分區鍵、排序鍵查詢
     */
    public <T> List<T> getQueryExpResult(Class<?> clazz, DynamoDBQueryExpression queryExp) {
        return dynamoDBMapper.query(clazz, queryExp);
    }
    
    
    /**
     * Query 分頁查詢
     */
    public <T> QueryResultPage getQueryPageExpResult(Class<T> clazz, DynamoDBQueryExpression queryExp) {
        return dynamoDBMapper.queryPage(clazz, queryExp);
    }
    
    /**
     * Scan 查詢
     */
    public List<?> getScanResult(Class<?> clazz, DynamoDBScanExpression scanExp) {
        return dynamoDBMapper.scan(clazz, scanExp);
    }
    
    /**
     * Scan 查詢  分頁查詢
     */
    public <T> ScanResultPage getScanPageResult(Class<T> clazz, DynamoDBScanExpression scanExp) {
        return dynamoDBMapper.scanPage(clazz, scanExp);
    }
}

 


免責聲明!

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



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