Статьи

Настройте проект SpringData с помощью Apache Cassandra

В этом посте мы будем использовать загрузку Gradle и Spring для создания проекта, объединяющего spring-mvc и базу данных Apache Cassandra.

Сначала мы начнем с нашей конфигурации Gradle

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
group 'com.gkatzioura'
version '1.0-SNAPSHOT'
 
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
 
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE")
    }
}
 
jar {
    baseName = 'gs-serving-web-content'
    version =  '0.1.0'
}
 
repositories {
    mavenCentral()
}
 
 
sourceCompatibility = 1.8
 
repositories {
    mavenCentral()
}
 
 
dependencies {
    compile "org.springframework.boot:spring-boot-starter-thymeleaf"
    compile "org.springframework.data:spring-data-cassandra:1.2.2.RELEASE"
    compile 'org.slf4j:slf4j-api:1.6.6'
    compile 'ch.qos.logback:logback-classic:1.0.13'
    testCompile "junit:junit"
}
 
task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

Мы создадим пространство ключей и таблицу в нашей базе данных Cassandra:

1
2
3
4
5
6
7
8
9
CREATE KEYSPACE IF NOT EXISTS example WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'AND durable_writes = true;
 
CREATE TABLE IF NOT EXISTS example.greetings (
    user text,
    id timeuuid,
    greet text,
    creation_date timestamp,
    PRIMARY KEY (user, id)
) WITH CLUSTERING ORDER BY (id DESC);

Мы можем запустить файл, содержащий операторы cql, используя cqlsh

1
cqlsh -f database_creation.cql

Информация о подключении Cassandra будет храниться в META-INF / cassandra.properties

1
2
3
cassandra.contactpoints=localhost
cassandra.port=9042
cassandra.keyspace=example

Теперь мы можем приступить к настройке Cassandra, используя весенние аннотации.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.gkatzioura.spring.config;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
 
 
@Configuration
@PropertySource(value = {"classpath:META-INF/cassandra.properties"})
@EnableCassandraRepositories(basePackages = {"com.gkatzioura.spring"})
public class CassandraConfig {
 
    @Autowired
    private Environment environment;
 
    private static final Logger LOGGER = LoggerFactory.getLogger(CassandraConfig.class);
 
    @Bean
    public CassandraClusterFactoryBean cluster() {
 
        CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
        cluster.setContactPoints(environment.getProperty("cassandra.contactpoints"));
        cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port")));
 
        return cluster;
    }
 
    @Bean
    public CassandraMappingContext mappingContext() {
        return new BasicCassandraMappingContext();
    }
 
    @Bean
    public CassandraConverter converter() {
        return new MappingCassandraConverter(mappingContext());
    }
 
    @Bean
    public CassandraSessionFactoryBean session() throws Exception {
 
        CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
        session.setCluster(cluster().getObject());
        session.setKeyspaceName(environment.getProperty("cassandra.keyspace"));
        session.setConverter(converter());
        session.setSchemaAction(SchemaAction.NONE);
 
        return session;
    }
 
    @Bean
    public CassandraOperations cassandraTemplate() throws Exception {
        return new CassandraTemplate(session().getObject());
    }
 
}

Затем мы создаем объект Greeting.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.gkatzioura.spring.entity;
 
import com.datastax.driver.core.utils.UUIDs;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
 
import java.util.Date;
import java.util.UUID;
 
@Table(value = "greetings")
public class Greeting {
 
    @PrimaryKeyColumn(name = "id",ordinal = 1,type = PrimaryKeyType.CLUSTERED)
    private UUID id = UUIDs.timeBased();
 
    @PrimaryKeyColumn(name="user",ordinal = 0,type = PrimaryKeyType.PARTITIONED)
    private String user;
 
    @Column(value = "greet")
    private String greet;
 
    @Column(value = "creation_date")
    private Date creationDate;
 
    public UUID getId() {
        return id;
    }
 
    public void setId(UUID id) {
        this.id = id;
    }
 
    public Date getCreationDate() {
        return creationDate;
    }
 
    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }
 
    public String getUser() {
        return user;
    }
 
    public void setUser(String user) {
        this.user = user;
    }
 
    public String getGreet() {
        return greet;
    }
 
    public void setGreet(String greet) {
        this.greet = greet;
    }
}

Для доступа к данным должен быть создан репозиторий. В нашем случае мы добавим некоторые дополнительные функции в хранилище, добавив несколько запросов.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package com.gkatzioura.spring.repository;
 
import com.gkatzioura.spring.entity.Greeting;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
 
import java.util.UUID;
 
public interface GreetRepository extends CassandraRepository<Greeting> {
 
    @Query("SELECT*FROM greetings WHERE user=?0 LIMIT ?1")
    Iterable<Greeting> findByUser(String user,Integer limit);
 
    @Query("SELECT*FROM greetings WHERE user=?0 AND id<?1 LIMIT ?2")
    Iterable<Greeting> findByUserFrom(String user,UUID from,Integer limit);
 
}

Теперь мы можем реализовать контроллер для доступа к данным через http. По почте мы можем сохранить Приветствие. Через get мы можем получить все полученные приветствия. Указав пользователя, мы можем использовать запрос Cassandra, чтобы получить приветствия для конкретного пользователя.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.gkatzioura.spring.controller;
 
import com.gkatzioura.spring.entity.Greeting;
import com.gkatzioura.spring.repository.GreetRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
@RestController
public class GreetingController {
 
    @Autowired
    private GreetRepository greetRepository;
 
    @RequestMapping(value = "/greeting",method = RequestMethod.GET)
    @ResponseBody
    public List<Greeting> greeting() {
        List<Greeting> greetings = new ArrayList<>();
        greetRepository.findAll().forEach(e->greetings.add(e));
        return greetings;
    }
 
    @RequestMapping(value = "/greeting/{user}/",method = RequestMethod.GET)
    @ResponseBody
    public List<Greeting> greetingUserLimit(@PathVariable String user,Integer limit) {
        List<Greeting> greetings = new ArrayList<>();
        greetRepository.findByUser(user,limit).forEach(e -> greetings.add(e));
        return greetings;
    }
 
    @RequestMapping(value = "/greeting",method = RequestMethod.POST)
    @ResponseBody
    public String saveGreeting(@RequestBody Greeting greeting) {
 
        greeting.setCreationDate(new Date());
        greetRepository.save(greeting);
 
        return "OK";
    }
 
}

Последний, но не менее важный наш класс Application

01
02
03
04
05
06
07
08
09
10
11
12
13
package com.gkatzioura.spring;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
}

Для запуска просто запустите:

1
gradle bootRun