Java NoSQL案例

wen java案例 1

本文目录导读:

Java NoSQL案例

  1. MongoDB案例(文档型数据库)
  2. Redis案例(键值存储)
  3. Cassandra案例(列族存储)
  4. Elasticsearch案例(搜索引擎)
  5. Neo4j案例(图数据库)
  6. 性能优化建议

我将为您提供几个Java中使用NoSQL数据库的完整案例,涵盖主流NoSQL数据库的使用方法。

MongoDB案例(文档型数据库)

Maven依赖

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.9.1</version>
</dependency>

基础操作案例

import com.mongodb.client.*;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import org.bson.Document;
import java.util.Arrays;
import java.util.Date;
public class MongoDBExample {
    public static void main(String[] args) {
        // 1. 连接MongoDB
        MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
        // 2. 获取数据库和集合
        MongoDatabase database = mongoClient.getDatabase("shop");
        MongoCollection<Document> collection = database.getCollection("users");
        // 3. 插入文档
        Document user = new Document("name", "张三")
                .append("age", 25)
                .append("email", "zhangsan@example.com")
                .append("createdAt", new Date())
                .append("address", new Document()
                        .append("city", "北京")
                        .append("street", "朝阳区")
                        .append("zipCode", "100000"));
        collection.insertOne(user);
        System.out.println("插入成功,ID: " + user.getObjectId("_id"));
        // 4. 批量插入
        collection.insertMany(Arrays.asList(
            new Document("name", "李四").append("age", 30),
            new Document("name", "王五").append("age", 28)
        ));
        // 5. 查询文档
        // 普通查询
        Document found = collection.find(Filters.eq("name", "张三")).first();
        System.out.println("查询结果: " + found);
        // 条件查询
        FindIterable<Document> results = collection.find(
            Filters.and(
                Filters.gte("age", 25),
                Filters.lt("age", 30)
            )
        );
        for (Document doc : results) {
            System.out.println("符合条件: " + doc);
        }
        // 6. 更新文档
        collection.updateOne(
            Filters.eq("name", "张三"),
            Updates.combine(
                Updates.set("age", 26),
                Updates.inc("visits", 1)
            )
        );
        // 7. 删除文档
        collection.deleteOne(Filters.eq("name", "李四"));
        // 8. 索引操作
        collection.createIndex(new Document("email", 1));
        collection.createIndex(new Document("age", -1).append("name", 1));
        mongoClient.close();
    }
}

Redis案例(键值存储)

Maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>3.1.0</version>
</dependency>

Spring Boot + Redis案例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.stereotype.Service;
@Service
public class RedisCacheService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // 缓存用户信息
    public void cacheUserInfo(String userId, UserInfo userInfo) {
        String key = "user:" + userId;
        // 使用Hash存储用户信息
        HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
        hashOps.put(key, "name", userInfo.getName());
        hashOps.put(key, "age", userInfo.getAge());
        hashOps.put(key, "email", userInfo.getEmail());
        // 设置过期时间(10分钟)
        redisTemplate.expire(key, 10, TimeUnit.MINUTES);
    }
    // 获取用户信息
    public UserInfo getUserInfo(String userId) {
        String key = "user:" + userId;
        HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
        UserInfo userInfo = new UserInfo();
        userInfo.setName((String) hashOps.get(key, "name"));
        userInfo.setAge((Integer) hashOps.get(key, "age"));
        userInfo.setEmail((String) hashOps.get(key, "email"));
        return userInfo;
    }
    // 缓存商品列表(使用List)
    public void cacheProductList(String categoryId, List<Product> products) {
        String key = "products:category:" + categoryId;
        redisTemplate.delete(key);
        // 批量添加
        products.forEach(product -> 
            redisTemplate.opsForList().rightPush(key, product)
        );
    }
    // 使用Redis实现分布式锁
    public boolean tryLock(String lockKey, long timeout) {
        // 使用SetNX命令
        return Boolean.TRUE.equals(
            redisTemplate.opsForValue().setIfAbsent(
                lockKey, 
                Thread.currentThread().getId(),
                timeout, 
                TimeUnit.SECONDS
            )
        );
    }
    // 计数器功能
    public long incrementCounter(String counterKey) {
        return redisTemplate.opsForValue().increment(counterKey);
    }
}

Cassandra案例(列族存储)

Maven依赖

<dependency>
    <groupId>com.datastax.oss</groupId>
    <artifactId>java-driver-core</artifactId>
    <version>4.15.0</version>
</dependency>
<dependency>
    <groupId>com.datastax.oss</groupId>
    <artifactId>java-driver-query-builder</artifactId>
    <version>4.15.0</version>
</dependency>

Cassandra操作案例

import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.*;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
public class CassandraExample {
    public static void main(String[] args) {
        // 1. 连接Cassandra
        try (CqlSession session = CqlSession.builder()
                .addContactPoint(new InetSocketAddress("localhost", 9042))
                .withLocalDatacenter("datacenter1")
                .withKeyspace("mykeyspace")
                .build()) {
            // 2. 创建表
            session.execute("""
                CREATE TABLE IF NOT EXISTS users (
                    user_id UUID PRIMARY KEY,
                    name TEXT,
                    email TEXT,
                    age INT,
                    city TEXT,
                    created_at TIMESTAMP
                )
                """);
            // 3. 插入数据
            PreparedStatement insert = session.prepare(
                "INSERT INTO users (user_id, name, email, age, city, created_at) VALUES (?, ?, ?, ?, ?, ?)"
            );
            BoundStatement bound = insert.bind(
                UUID.randomUUID(),
                "张三",
                "zhangsan@example.com",
                25,
                "北京",
                new Date()
            );
            session.execute(bound);
            // 4. 查询数据
            ResultSet resultSet = session.execute("SELECT * FROM users WHERE user_id = ?", userId);
            Row row = resultSet.one();
            if (row != null) {
                System.out.println("用户: " + row.getString("name"));
                System.out.println("邮箱: " + row.getString("email"));
                System.out.println("年龄: " + row.getInt("age"));
            }
            // 5. 索引查询(Cassandra 3.4+)
            session.execute("CREATE INDEX IF NOT EXISTS idx_users_age ON users(age)");
            ResultSet ageResults = session.execute("SELECT * FROM users WHERE age > 20 ALLOW FILTERING");
            // 6. 更新数据
            session.execute(
                "UPDATE users SET age = 26, city = '上海' WHERE user_id = ?", 
                userId
            );
            // 7. 使用QueryBuilder
            Statement select = QueryBuilder.selectFrom("users")
                .columns("user_id", "name", "email")
                .whereColumn("city").isEqualTo(QueryBuilder.literal("北京"))
                .build();
            ResultSet queryBuilderResult = session.execute(select);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Elasticsearch案例(搜索引擎)

Maven依赖

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.17.9</version>
</dependency>

搜索引擎案例

import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class ElasticsearchExample {
    private RestHighLevelClient client;
    public ElasticsearchExample() {
        client = new RestHighLevelClient(
            RestClient.builder(new HttpHost("localhost", 9200, "http"))
        );
    }
    // 创建索引
    public void createIndex(String indexName) throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        request.mapping("""
            {
                "properties": {
                    "title": { "type": "text", "analyzer": "ik_max_word" },
                    "content": { "type": "text", "analyzer": "ik_max_word" },
                    "publishDate": { "type": "date" },
                    "category": { "type": "keyword" }
                }
            }
            """, XContentType.JSON);
        client.indices().create(request, RequestOptions.DEFAULT);
    }
    // 添加文档
    public void addDocument(String indexName, String id, String title, 
                           String content, String category) throws IOException {
        IndexRequest request = new IndexRequest(indexName);
        request.id(id);
        Map<String, Object> document = new HashMap<>();
        document.put("title", title);
        document.put("content", content);
        document.put("category", category);
        document.put("publishDate", new Date());
        request.source(document);
        client.index(request, RequestOptions.DEFAULT);
    }
    // 搜索文档
    public List<Map<String, Object>> search(String indexName, 
                                           String query) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 构建搜索查询
        sourceBuilder.query(
            QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("title", query))
                .should(QueryBuilders.matchQuery("content", query))
                .minimumShouldMatch(1)
        );
        // 分页设置
        sourceBuilder.from(0);
        sourceBuilder.size(10);
        // 排序
        sourceBuilder.sort("publishDate", SortOrder.DESC);
        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        List<Map<String, Object>> results = new ArrayList<>();
        for (SearchHit hit : response.getHits().getHits()) {
            results.add(hit.getSourceAsMap());
        }
        return results;
    }
    // 删除文档
    public void deleteDocument(String indexName, String id) throws IOException {
        DeleteRequest request = new DeleteRequest(indexName, id);
        client.delete(request, RequestOptions.DEFAULT);
    }
}

Neo4j案例(图数据库)

Maven依赖

<dependency>
    <groupId>org.neo4j.driver</groupId>
    <artifactId>neo4j-java-driver</artifactId>
    <version>5.9.0</version>
</dependency>

图数据库案例

import org.neo4j.driver.*;
import static org.neo4j.driver.Values.parameters;
public class Neo4jExample implements AutoCloseable {
    private final Driver driver;
    public Neo4jExample(String uri, String user, String password) {
        driver = GraphDatabase.driver(uri, AuthTokens.basic(user, password));
    }
    // 创建社交网络节点和关系
    public void createSocialNetwork() {
        try (Session session = driver.session()) {
            session.run("CREATE (zhangsan:Person {name: '张三', age: 30})");
            session.run("CREATE (lisi:Person {name: '李四', age: 28})");
            // 创建关系
            session.run("""
                MATCH (a:Person {name: '张三'}), (b:Person {name: '李四'})
                CREATE (a)-[r:FOLLOWS]->(b)
                """);
            // 创建朋友关系
            session.run("""
                MATCH (a:Person {name: '张三'}), (b:Person {name: '李四'})
                CREATE (a)-[r:FRIEND_OF {since: 2020}]->(b)
                """);
        }
    }
    // 查询朋友关系
    public void findFriends(String personName) {
        try (Session session = driver.session()) {
            Result result = session.run(
                "MATCH (p:Person {name: $name})-[:FRIEND_OF]->(friends) RETURN friends.name AS name, friends.age AS age",
                parameters("name", personName)
            );
            while (result.hasNext()) {
                Record record = result.next();
                System.out.println("朋友: " + record.get("name").asString() + 
                                 ",年龄: " + record.get("age").asInt());
            }
        }
    }
    // 查找推荐好友(朋友的朋友)
    public void findFriendSuggestions(String personName) {
        try (Session session = driver.session()) {
            Result result = session.run("""
                MATCH (p:Person {name: $name})-[:FRIEND_OF]->(friend)-[:FRIEND_OF]->(suggestion)
                WHERE suggestion.name <> $name
                AND NOT (p)-[:FRIEND_OF]->(suggestion)
                RETURN DISTINCT suggestion.name AS name, suggestion.age AS age
                LIMIT 5
                """, 
                parameters("name", personName));
            while (result.hasNext()) {
                Record record = result.next();
                System.out.println("推荐好友: " + record.get("name").asString());
            }
        }
    }
    // 删除关系
    public void removeFriend(String person1, String person2) {
        try (Session session = driver.session()) {
            session.run("""
                MATCH (a:Person {name: $name1})-[r]->(b:Person {name: $name2})
                DELETE r
                """,
                parameters("name1", person1, "name2", person2));
        }
    }
    @Override
    public void close() {
        driver.close();
    }
}

性能优化建议

MongoDB优化

public class MongoDBPerformance {
    // 使用批量插入提高性能
    public void bulkInsert(List<Document> documents) {
        MongoCollection<Document> collection = getCollection();
        // 每批1000条
        BulkWriteOptions bulkWriteOptions = new BulkWriteOptions().ordered(false);
        List<WriteModel<Document>> bulkOperations = documents.stream()
            .map(doc -> new InsertOneModel<>(doc))
            .collect(Collectors.toList());
        BulkWriteResult result = collection.bulkWrite(bulkOperations, bulkWriteOptions);
    }
    // 查询优化 - 使用投影只获取必要字段
    public void optimizedQuery() {
        MongoCollection<Document> collection = getCollection();
        Document projection = new Document("name", 1)
                .append("age", 1)
                .append("_id", 0);
        FindIterable<Document> iterable = collection.find(
            new Document("age", new Document("$gt", 25))
        ).projection(projection).limit(100);
        // 使用batch size
        iterable.batchSize(500);
    }
}

Redis优化

@Component
public class RedisPerformance {
    @Autowired
    private StringRedisTemplate redisTemplate;
    // 使用pipeline批量操作
    public void batchOperations() {
        List<Object> results = redisTemplate.executePipelined(
            (RedisCallback<Object>) connection -> {
                connection.set("key1".getBytes(), "value1".getBytes());
                connection.set("key2".getBytes(), "value2".getBytes());
                connection.get("key1".getBytes());
                return null;
            }
        );
    }
    // 使用Lua脚本实现原子操作
    public void useLuaScript() {
        DefaultRedisScript<String> script = new DefaultRedisScript<>();
        script.setScriptText("""
            local current = tonumber(redis.call('get', KEYS[1]))
            local new = tonumber(ARGV[1])
            if current >= new then
                return current
            end
            redis.call('set', KEYS[1], new)
            return new
            """);
        script.setResultType(String.class);
        redisTemplate.execute(script, 
            Arrays.asList("counter"), 
            "100"
        );
    }
}

这些案例展示了Java中主流NoSQL数据库的基本使用方法:

  • MongoDB:文档型,适合灵活的数据结构和快速开发
  • Redis:键值型,适合缓存、会话管理和实时统计
  • Cassandra:列族型,适合大规模分布式系统
  • Elasticsearch:搜索引擎,适合全文搜索和分析
  • Neo4j:图型,适合关系密集型数据

选择NoSQL数据库时,应根据业务需求考虑:

  • 数据结构特征(结构化、半结构化、非结构化)
  • 查询模式(等值查询、范围查询、全文搜索、图查询)
  • 扩展需求(水平扩展、垂直扩展)
  • 一致性要求(强一致、最终一致)
  • 运维复杂度

每个数据库都有其特定的优点和适用场景,合理选择能够大大提高应用性能和开发效率。

上一篇Redis案例

下一篇JCL案例

抱歉,评论功能暂时关闭!