原题目:Spring认证中国教育管理中心-Apache Cassandra 的 Spring 数据教程二(Spring中国教育管理中心)

9.3.2.XML 配置
本节介绍如何应用 XML 配置 Spring Data Cassandra。

内部化连贯属性
要内部化连贯属性,您应该首先创立一个属性文件,其中蕴含连贯到 Cassandra 所需的信息。contactpoints和keyspace是必填字段。

以下示例显示了咱们的属性文件,名为cassandra.properties:

cassandra.contactpoints=10.1.55.80:9042,10.1.55.81:9042
cassandra.keyspace=showcase
在接下来的两个示例中,咱们应用 Spring 将这些属性加载到 Spring 上下文中。

应用基于 XML 的元数据注册会话实例
尽管您能够应用 Spring 的传统<beans/>XML 命名空间向
com.datastax.oss.driver.api.core.CqlSession容器注册一个实例 ,但 XML 可能十分简短,因为它是通用的。XML 名称空间是配置罕用对象(例如CqlSession实例)的更好代替办法。该cassandra命名空间让你创立一个CqlSession实例。

以下示例显示了如何配置cassandra命名空间:

示例 58. 应用cassandra命名空间配置 Cassandra 的 XML 模式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
xsi:schemaLocation="

http://www.springframework.org/schema/data/cassandrahttps://www.springframework.org/schema/data/cassandra/spring-cassandra.xsdhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- Default bean name is 'cassandraSession' -->
<cassandra:session contact-points="localhost" port="9042">

<cassandra:keyspace action="CREATE_DROP" name="mykeyspace" />

</cassandra:session>

<cassandra:session-factory>

<cassandra:script        location="classpath:/org/springframework/data/cassandra/config/schema.cql"/>

</cassandra:session-factory>
</beans>
Spring认证中国教育管理中心-Apache Cassandra 的 Spring 数据教程二
更高级的 Cassandra 配置的 XML 配置元素如下所示。这些元素都应用默认的 bean 名称来放弃配置代码的整洁和可读。

尽管后面的示例显示了配置 Spring 以连贯到 Cassandra 是如许容易,但还有许多其余选项。基本上,DataStax Java 驱动程序可用的任何选项也可在 Spring Data for Apache Cassandra 配置中应用。这包含但不限于身份验证、负载平衡策略、重试策略和池选项。所有 Spring Data for Apache Cassandra 办法名称和 XML 元素都与驱动程序上的配置选项齐全(或尽可能靠近)命名,以便映射任何现有的驱动程序配置应该是间接的。以下示例展现了如何应用 XML 配置 Spring Data 组件

示例 59. 应用 XML 配置 Spring Data 组件

<!-- Loads the properties into the Spring Context and uses them to fill
in placeholders in the bean definitions -->
<context:property-placeholder location="classpath:cassandra.properties" />

<!-- REQUIRED: The Cassandra Session -->
<cassandra:session contact-points="${cassandra.contactpoints}" keyspace-name="${cassandra.keyspace}" />

<!-- REQUIRED: The default Cassandra mapping context used by CassandraConverter -->
<cassandra:mapping>
<cassandra:user-type-resolver keyspace-name="${cassandra.keyspace}" />
</cassandra:mapping>

<!-- REQUIRED: The default Cassandra converter used by CassandraTemplate -->
<cassandra:converter />

<!-- REQUIRED: The Cassandra template is the foundation of all Spring
Data Cassandra -->
<cassandra:template id="cassandraTemplate" />

<!-- OPTIONAL: If you use Spring Data for Apache Cassandra repositories, add
your base packages to scan here -->
<cassandra:repositories base-package="org.spring.cassandra.example.repo" />
Spring认证中国教育管理中心-Apache Cassandra 的 Spring 数据教程二
9.4.模式治理
Apache Cassandra 是一种数据存储,须要在任何数据交互之前进行模式定义。Spring Data for Apache Cassandra 能够反对您创立模式。

9.4.1.键空间和生命周期脚本
首先是一个 Cassandra 键空间。键空间是共享雷同复制因子和复制策略的表的逻辑分组。Keyspace 治理位于CqlSession配置中,其中有KeyspaceSpecification启动和敞开 CQL 脚本执行。

应用标准申明键空间容许创立和删除键空间。它从标准中派生出 CQL,因而您无需本人编写 CQL。以下示例应用 XML 指定 Cassadra 键空间:

示例 60. 应用 XML 指定 Cassandra 键空间

<cassandra:session>

<cassandra:keyspace action="CREATE_DROP" durable-writes="true" name="my_keyspace">    <cassandra:replication class="NETWORK_TOPOLOGY_STRATEGY">      <cassandra:data-center name="foo" replication-factor="1" />      <cassandra:data-center name="bar" replication-factor="2" />    </cassandra:replication>

</cassandra:keyspace>

</cassandra:session>
您还能够应用 Java 配置指定 Cassandra 密钥空间,如以下示例所示:

示例 61. 应用 Java 配置指定 Cassandra 键空间

@Configuration
public class CreateKeyspaceConfiguration extends AbstractCassandraConfiguration implements BeanClassLoaderAware {

@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {

CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace("my_keyspace")    .with(KeyspaceOption.DURABLE_WRITES, true)    .withNetworkReplication(DataCenterReplication.of("foo", 1), DataCenterReplication.of("bar", 2));return Arrays.asList(specification);

}

@Override
protected List<DropKeyspaceSpecification> getKeyspaceDrops() {

return Arrays.asList(DropKeyspaceSpecification.dropKeyspace("my_keyspace"));

}

// ...
}
Spring认证中国教育管理中心-Apache Cassandra 的 Spring 数据教程二
密钥空间创立容许疾速疏导,无需内部密钥空间治理。这对某些场景很有用,但应审慎应用。在应用程序敞开时删除键空间会从键空间中的表中删除键空间和所有数据。

9.4.2.初始化一个SessionFactory

org.springframework.data.cassandra.core.cql.session.init包提供对初始化现有SessionFactory. 您有时可能须要初始化在某处服务器上运行的密钥空间。

初始化密钥空间
您能够CqlSession在配置的键空间中提供在初始化和敞开时执行的任意 CQL ,如以下 Java 配置示例所示:

@Configuration
public class KeyspacePopulatorConfiguration extends AbstractCassandraConfiguration {

@Nullable
@Override
protected KeyspacePopulator keyspacePopulator() {

return new ResourceKeyspacePopulator(scriptOf("CREATE TABLE my_table …"));

}

@Nullable
@Override
protected KeyspacePopulator keyspaceCleaner() {

return new ResourceKeyspacePopulator(scriptOf("DROP TABLE my_table;"));

}

// ...
}
如果要应用 XML 配置初始化数据库并且能够提供对SessionFactorybean的援用,则能够应用命名空间中的initialize-keyspace标记cassandra:

<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory">

<cassandra:script location="classpath:com/foo/cql/db-schema.cql"/><cassandra:script location="classpath:com/foo/cql/db-test-data.cql"/>

</cassandra:initialize-keyspace>
后面的示例针对键空间运行两个指定的脚本。第一个脚本创立模式,第二个脚本应用测试数据集填充表。脚本地位也能够是 Spring 中用于资源的通常 Ant 款式中的带通配符的模式(例如,classpath:/com/foo//cql/-data.cql)。如果应用模式,脚本将按其 URL 或文件名的词法程序运行。

键空间初始值设定项的默认行为是无条件运行提供的脚本。这可能并不总是您想要的——例如,如果您针对已蕴含测试数据的键空间运行脚本。通过遵循先创立表而后插入数据的常见模式(如后面所示),能够升高意外删除数据的可能性。如果表已存在,则第一步将失败。

然而,为了更好地管制现有数据的创立和删除,XML 命名空间提供了一些附加选项。第一个是关上和敞开初始化的标记。您能够依据环境进行设置(例如从零碎属性或环境 bean 中提取布尔值)。以下示例从零碎属性中获取值:

<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory"

enabled="#{systemProperties.INITIALIZE_KEYSPACE}">    <cassandra:script location="..."/>

</cassandra:initialize-database>
enabled从名为 的零碎属性获取值INITIALIZE_KEYSPACE。

管制现有数据产生的状况的第二个选项是更能容忍失败。为此,您能够管制初始化程序疏忽它从脚本执行的 CQL 中的某些谬误的能力,如以下示例所示:

<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory" ignore-failures="DROPS">

<cassandra:script location="..."/>

</cassandra:initialize-database>
在后面的示例中,咱们说咱们冀望脚本有时针对空的键空间运行DROP,因而脚本中的某些语句会失败。所以失败的 CQLDROP语句将被疏忽,但其余失败将导致异样。如果您不想应用反对DROP … IF EXISTS(或相似的),但您想在从新创立之前无条件地删除所有测试数据,这将很有用。在这种状况下,第一个脚本通常是一组DROP语句,而后是一组CREATE语句。

该ignore-failures选项能够设置为NONE(默认)、DROPS(疏忽失败的抛弃)或ALL(疏忽所有失败)。

;如果;脚本中基本不存在该字符,则每个语句都应由或 一个新行分隔。您能够通过脚本进行全局或脚本管制,如下例所示:

@Configuration
public class SessionFactoryInitializerConfiguration extends AbstractCassandraConfiguration {

@Bean
SessionFactoryInitializer sessionFactoryInitializer(SessionFactory sessionFactory) {

SessionFactoryInitializer initializer = new SessionFactoryInitializer();initializer.setSessionFactory(sessionFactory);ResourceKeyspacePopulator populator1 = new ResourceKeyspacePopulator();populator1.setSeparator(";");populator1.setScripts(new ClassPathResource("com/myapp/cql/db-schema.cql"));ResourceKeyspacePopulator populator2 = new ResourceKeyspacePopulator();populator2.setSeparator("@@");populator2.setScripts(new ClassPathResource("classpath:com/myapp/cql/db-test-data-1.cql"), //    new ClassPathResource("classpath:com/myapp/cql/db-test-data-2.cql"));initializer.setKeyspacePopulator(new CompositeKeyspacePopulator(populator1, populator2));return initializer;

}

// ...
}
Spring认证中国教育管理中心-Apache Cassandra 的 Spring 数据教程二
或者,您能够应用 XML 来配置SessionFactoryInitializer:

<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory" separator="@@">

<cassandra:script location="classpath:com/myapp/cql/db-schema.cql" separator=";"/>     <cassandra:script location="classpath:com/myapp/cql/db-test-data-1.cql"/><cassandra:script location="classpath:com/myapp/cql/db-test-data-2.cql"/>

</cassandra:initialize-keyspace>
将分隔符脚本设置为@@.

设置分隔符db-schema.cql来;。

在此示例中,两个test-data脚本@@用作语句分隔符,并且仅db-schema.cql应用;. 此配置指定默认分隔符是@@并笼罩db-schema脚本的默认值。

如果您须要比从 XML 命名空间取得更多的管制,您能够SessionFactoryInitializer间接应用并将其定义为应用程序中的组件。

依赖键空间的其余组件的初始化
一大类应用程序(那些在 Spring 上下文启动后才应用数据库的应用程序)能够应用数据库初始化程序而不会呈现进一步的简单状况。如果您的应用程序不是其中之一,您可能须要浏览本节的其余部分。

数据库初始化程序依赖于一个SessionFactory实例并运行其初始化回调中提供的脚本(相似于init-methodXML bean 定义中的 、@PostConstruct组件中的afterPropertiesSet()办法或实现 的组件中的办法InitializingBean)。如果其余 bean 依赖雷同的数据源并在初始化回调中应用会话工厂,则可能存在问题,因为数据尚未初始化。一个常见的例子是缓存,它会在应用程序启动时急迫地初始化并从数据库加载数据。

要解决此问题,您有两种抉择:将缓存初始化策略更改为稍后阶段或确保首先初始化键空间初始化程序。

如果应用程序在您的管制之下而不是在其余状况下,则更改缓存初始化策略可能很容易。对于如何实现这一点的一些倡议包含:

使缓存在第一次应用时提早初始化,从而缩短应用程序启动工夫。
让您的缓存或初始化缓存的独自组件实现Lifecycle或SmartLifecycle。当应用程序上下文启动时,您能够SmartLifecycle通过设置其autoStartup标记来主动启动 a ,并且您能够Lifecycle通过调用ConfigurableApplicationContext.start()关闭的上下文来手动启动 a 。
应用 SpringApplicationEvent或相似的自定义观察器机制来触发缓存初始化。ContextRefreshedEvent当上下文筹备好应用时(在所有 bean 曾经初始化之后),它总是由上下文公布,所以这通常是一个有用的钩子(这是SmartLifecycle默认状况下的工作形式)。
确保首先初始化键空间初始化器也很容易。对于如何实现这一点的一些倡议包含:

依赖 Spring 的默认行为,BeanFactory即 bean 按注册程序初始化。您能够通过采纳<import/>XML 配置中的一组元素来对利用程序模块进行排序的常见做法,并确保首先列出数据库和数据库初始化,从而轻松地进行安顿。
将SessionFactory应用它的业务组件和应用它的业务组件离开,并通过将它们放在独自的ApplicationContext实例中来管制它们的启动程序(例如,父上下文蕴含SessionFactory,子上下文蕴含业务组件)。这种构造在 Spring Web 应用程序中很常见,但能够更广泛地利用。
应用表和用户定义类型的模式治理应用 Spring Data Cassandra 的内置模式生成器初始化键空间。
9.4.3.表和用户定义的类型
Spring Data for Apache Cassandra 应用适宜您的数据模型的映射实体类来解决数据拜访。您能够应用这些实体类来创立 Cassandra 表标准和用户类型定义。

架构创立与CqlSession初始化相关联SchemaAction。反对以下操作:

SchemaAction.NONE: 没有创立或删除表或类型。这是默认设置。
SchemaAction.CREATE:从用@Table正文的实体和用正文的类型创立表、索引和用户定义的类型@UserDefinedType。如果您尝试创立类型,现有表或类型会导致谬误。
SchemaAction.CREATE_IF_NOT_EXISTS: 喜爱SchemaAction.CREATE但IF NOT EXISTS利用。现有的表或类型不会导致任何谬误,但可能会放弃古老。
SchemaAction.RECREATE:删除并从新创立已知要应用的现有表和类型。未在应用程序中配置的表和类型不会被删除。
SchemaAction.RECREATE_DROP_UNUSED:删除所有表和类型并仅从新创立已知的表和类型。
SchemaAction.RECREATE并
SchemaAction.RECREATE_DROP_UNUSED删除您的表并失落所有数据。 RECREATE_DROP_UNUSED还会删除应用程序未知的表和类型。

为模式治理启用表和用户定义的类型
基于元数据的映射解释了具备约定和正文的对象映射。为了避免将不须要的类创立为表或类型,模式治理仅对用 正文的实体@Table和用正文的用户定义类型无效@UserDefinedType。通过扫描类门路发现实体。实体扫描须要一个或多个根底包。应用的元组类型列TupleValue不提供任何类型详细信息。因而,您必须正文此类列属性@CassandraType(type = TUPLE, typeArguments = …) 以指定所需的列类型。

以下示例显示了如何在 XML 配置中指定实体根底包:

示例 62. 应用 XML 配置指定实体根底包

<cassandra:mapping entity-base-packages="com.foo,com.bar"/>
以下示例显示了如何在 Java 配置中指定实体根底包:

示例 63.应用 Java 配置指定实体根底包

@Configuration
public class EntityBasePackagesConfiguration extends AbstractCassandraConfiguration {

@Override
public String[] getEntityBasePackages() {

return new String[] { "com.foo", "com.bar" };

}

// ...
}