Skip to content

Commit 9711e36

Browse files
committed
Merge branch '2.1' into 3.0
2 parents 687af26 + ac4e8bc commit 9711e36

17 files changed

Lines changed: 714 additions & 33 deletions

File tree

manual/README.md

Lines changed: 295 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,302 @@
11
## Manual
22

3-
This part of the documentation is organized into sub-sections covering
4-
specific topics.
3+
### Quick start
4+
5+
Here's a short program that connects to Cassandra and executes a query:
6+
7+
```java
8+
Cluster cluster = null;
9+
try {
10+
cluster = Cluster.builder() // (1)
11+
.addContactPoint("127.0.0.1")
12+
.build();
13+
Session session = cluster.connect(); // (2)
14+
15+
ResultSet rs = session.execute("select release_version from system.local"); // (3)
16+
Row row = rs.one();
17+
System.out.println(row.getString("release_version")); // (4)
18+
} finally {
19+
if (cluster != null) cluster.close(); // (5)
20+
}
21+
```
22+
23+
1. the [Cluster] object is the main entry point of the driver. It holds the known state of the actual Cassandra cluster
24+
(notably the [Metadata](metadata/)). This class is thread-safe, you should create a single instance (per target
25+
Cassandra cluster), and share it throughout your application;
26+
2. the [Session] is what you use to execute queries. Likewise, it is thread-safe and should be reused;
27+
3. we use `execute` to send a query to Cassandra. This returns a [ResultSet], which is essentially a collection of [Row]
28+
objects. On the next line, we extract the first row (which is the only one in this case);
29+
4. we extract the value of the first (and only) column from the row;
30+
5. finally, we close the cluster after we're done with it. This will also close any session that was created from this
31+
cluster. This step is important because it frees underlying resources (TCP connections, thread pools...). In a real
32+
application, you would typically do this at shutdown (for example, when undeploying your webapp).
33+
34+
Note: this example uses the synchronous API. Most methods have [asynchronous](async/) equivalents.
35+
36+
37+
### Setting up the driver
38+
39+
#### [Cluster]
40+
41+
##### Creating an instance
42+
43+
The simplest approach is to do it programmatically with [Cluster.Builder], which provides a fluent API:
44+
45+
```java
46+
Cluster cluster = Cluster.builder()
47+
.withClusterName("myCluster")
48+
.addContactPoint("127.0.0.1")
49+
.build();
50+
```
51+
52+
Alternatively, you might want to retrieve the settings from an external source (like a properties file or a web
53+
service). You'll need to provide an implementation of [Initializer] that loads these settings:
54+
55+
```java
56+
Initializer myInitializer = ... // your implementation
57+
Cluster cluster = Cluster.buildFrom(myInitializer);
58+
```
59+
60+
##### Creation options
61+
62+
The only required option is the list of contact points, i.e. the hosts that the driver will initially contact to
63+
discover the cluster topology. You can provide a single contact point, but it is usually a good idea to provide more, so
64+
that the driver can fallback if the first one is down.
65+
66+
The other aspects that you can configure on the `Cluster` are:
67+
68+
* [address translation](address_resolution/);
69+
* [authentication](auth/);
70+
* [compression](compression/);
71+
* [load balancing](load_balancing/);
72+
* [metrics](metrics/);
73+
* low-level [Netty configuration][NettyOptions];
74+
* [query options][QueryOptions];
75+
* [reconnections](reconnection/);
76+
* [retries](retries/);
77+
* [socket options][SocketOptions];
78+
* [SSL](ssl/);
79+
* [speculative executions](speculative_execution/);
80+
* [query timestamps](query_timestamps/).
81+
82+
In addition, you can register various types of listeners to be notified of cluster events; see [Host.StateListener],
83+
[LatencyTracker], and [SchemaChangeListener].
84+
85+
##### Cluster initialization
86+
87+
A freshly-built `Cluster` instance does not initialize automatically; that will be triggered by one of the following
88+
actions:
89+
90+
* an explicit call to `cluster.init()`;
91+
* a call to `cluster.getMetadata()`;
92+
* creating a session with `cluster.connect()` or one of its variants;
93+
* calling `session.init()` on a session that was created with `cluster.newSession()`.
94+
95+
The initialization sequence is the following:
96+
97+
* initialize internal state (thread pools, utility components, etc.);
98+
* try to connect to each of the contact points in sequence. The order is not deterministic (in fact, the driver shuffles
99+
the list to avoid hotspots if a large number of clients share the same contact points). If no contact point replies,
100+
a [NoHostAvailableException] is thrown and the process stops here;
101+
* otherwise, the successful contact point is elected as the [control host](control_connection/). The driver negotiates
102+
the [native protocol version](native_protocol/) with it, and queries its system tables to discover the addresses of
103+
the other hosts.
104+
105+
Note that, at this stage, only the control connection has been established. Connections to other hosts will only be
106+
opened when a session gets created.
107+
108+
#### [Session]
109+
110+
By default, a session isn't tied to any specific keyspace. You'll need to prefix table names in your queries:
111+
112+
```java
113+
Session session = cluster.connect();
114+
session.execute("select * from myKeyspace.myTable where id = 1");
115+
```
116+
117+
You can also specify a keyspace name at construction time, it will be used as the default when table names are not
118+
qualified:
119+
120+
```java
121+
Session session = cluster.connect("myKeyspace");
122+
session.execute("select * from myTable where id = 1");
123+
session.execute("select * from otherKeyspace.otherTable where id = 1");
124+
```
125+
126+
You might be tempted to open a separate session for each keyspace used in your application; however, note that
127+
[connection pools](pooling/) are created at the session level, so each new session will consume additional system
128+
resources:
129+
130+
```java
131+
// Warning: creating two sessions doubles the number of TCP connections opened by the driver
132+
Session session1 = cluster.connect("ks1");
133+
Session session2 = cluster.connect("ks2");
134+
```
135+
136+
Also, there is currently a [known limitation](async/#known-limitations) with named sessions, that causes the driver to
137+
unexpectedly block the calling thread in certain circumstances; if you use a fully asynchronous model, you should use a
138+
session with no keyspace.
139+
140+
Finally, if you issue a `USE` statement, it will change the default keyspace on that session:
141+
142+
```java
143+
Session session = cluster.connect();
144+
// No default keyspace set, need to prefix:
145+
session.execute("select * from myKeyspace.myTable where id = 1");
146+
147+
session.execute("USE myKeyspace");
148+
// Now the keyspace is set, unqualified query works:
149+
session.execute("select * from myTable where id = 1");
150+
```
151+
152+
Be very careful though: if the session is shared by multiple threads, switching the keyspace at runtime could easily
153+
cause unexpected query failures.
154+
155+
Generally, the recommended approach is to use a single session with no keyspace, and prefix all your queries.
156+
157+
158+
### Running queries
159+
160+
You run queries with the session's `execute` method:
161+
162+
```java
163+
ResultSet rs = session.execute("select release_version from system.local");
164+
```
165+
166+
As shown here, the simplest form is to pass a query string directly. You can also pass an instance of
167+
[Statement](statements/).
168+
169+
#### Processing rows
170+
171+
Executing a query produces a [ResultSet], which is an iterable of [Row]. The basic way to process all rows is to use
172+
Java's for-each loop:
173+
174+
```java
175+
for (Row row : rs) {
176+
// process the row
177+
}
178+
```
179+
180+
Note that this will return **all results** without limit (even though the driver might use multiple queries in the
181+
background). To handle large result sets, you might want to use a `LIMIT` clause in your CQL query, or use one of the
182+
techniques described in the [paging](paging/) documentation.
183+
184+
When you know that there is only one row (or are only interested in the first one), the driver provides a convenience
185+
method:
186+
187+
```java
188+
Row row = rs.one();
189+
```
190+
191+
#### Reading columns
192+
193+
[Row] provides getters to extract column values; they can be either positional or named:
194+
195+
```java
196+
Row row = session.execute("select first_name, last_name from users where id = 1").one();
197+
198+
// The two are equivalent:
199+
String firstName = row.getString(0);
200+
String firstName = row.getString("first_name");
201+
```
202+
203+
##### CQL to Java type mapping
204+
205+
<table border="1" style="text-align:center; width:100%;margin-bottom:1em;">
206+
<tr> <td><b>CQL3 data type</b></td> <td><b>Getter name</b></td> <td><b>Java type</b></td> </tr>
207+
<tr> <td>ascii</td> <td>getString</td> <td>java.lang.String</td> </tr>
208+
<tr> <td>bigint</td> <td>getLong</td> <td>long</td> </tr>
209+
<tr> <td>blob</td> <td>getBytes</td> <td>java.nio.ByteBuffer</td> </tr>
210+
<tr> <td>boolean</td> <td>getBool</td> <td>boolean</td> </tr>
211+
<tr> <td>counter</td> <td>getLong</td> <td>long</td> </tr>
212+
<tr> <td>date</td> <td>getDate</td> <td><a href="http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/LocalDate.html">LocalDate</a></td> </tr>
213+
<tr> <td>decimal</td> <td>getDecimal</td> <td>java.math.BigDecimal</td> </tr>
214+
<tr> <td>double</td> <td>getDouble</td> <td>double</td> </tr>
215+
<tr> <td>float</td> <td>getFloat</td> <td>float</td> </tr>
216+
<tr> <td>inet</td> <td>getInet</td> <td>java.net.InetAddress</td> </tr>
217+
<tr> <td>int</td> <td>getInt</td> <td>int</td> </tr>
218+
<tr> <td>list</td> <td>getList</td> <td>java.util.List<T></td> </tr>
219+
<tr> <td>map</td> <td>getMap</td> <td>java.util.Map<K, V></td> </tr>
220+
<tr> <td>set</td> <td>getSet</td> <td>java.util.Set<T></td> </tr>
221+
<tr> <td>smallint</td> <td>getShort</td> <td>short</td> </tr>
222+
<tr> <td>text</td> <td>getString</td> <td>java.lang.String</td> </tr>
223+
<tr> <td>time</td> <td>getTime</td> <td>long</td> </tr>
224+
<tr> <td>timestamp</td> <td>getTimestamp</td> <td>java.util.Date</td> </tr>
225+
<tr> <td>timeuuid</td> <td>getUUID</td> <td>java.util.UUID</td> </tr>
226+
<tr> <td>tinyint</td> <td>getByte</td> <td>byte</td> </tr>
227+
<tr> <td>tuple</td> <td>getTupleValue</td> <td><a href="tuples/">TupleValue</a></td> </tr>
228+
<tr> <td>user-defined types</td> <td>getUDTValue</td> <td><a href="udts/">UDTValue</a></td> </tr>
229+
<tr> <td>uuid</td> <td>getUUID</td> <td>java.util.UUID</td> </tr>
230+
<tr> <td>varchar</td> <td>getString</td> <td>java.lang.String</td> </tr>
231+
<tr> <td>varint</td> <td>getVarint</td> <td>java.math.BigInteger</td> </tr>
232+
</table>
233+
234+
In addition to these default mappings, you can register your own types with [custom codecs](custom_codecs/).
235+
236+
##### Primitive types
237+
238+
For performance reasons, the driver uses primitive Java types wherever possible (`boolean`, `int`...); the CQL value
239+
`NULL` is encoded as the type's default value (`false`, `0`...), which can be ambiguous. To distinguish `NULL` from
240+
actual values, use `isNull`:
241+
242+
```java
243+
Integer age = row.isNull("age") ? null : row.getInt("age");
244+
```
245+
246+
##### Collection types
247+
248+
To ensure type safety, collection getters are generic. You need to provide type parameters matching your CQL type when
249+
calling the methods:
250+
251+
```java
252+
// Assuming given_names is a list<text>:
253+
List<String> givenNames = row.getList("given_names", String.class);
254+
```
255+
256+
For nested collections, element types are generic and cannot be expressed as Java `Class` instances. We use Guava's
257+
[TypeToken](https://github.com/google/guava/wiki/ReflectionExplained) instead:
258+
259+
```java
260+
// Assuming teams is a set<list<text>>:
261+
TypeToken<List<String>> listOfStrings = new TypeToken<List<String>>() {};
262+
Set<List<String>> teams = row.getSet("teams", listOfStrings);
263+
```
264+
265+
Since type tokens are anonymous inner classes, it's recommended to store them as constants in a utility class instead of
266+
re-creating them each time.
267+
268+
##### Row metadata
269+
270+
`Row` exposes an API to explore the column metadata at runtime:
271+
272+
```java
273+
for (ColumnDefinitions.Definition definition : row.getColumnDefinitions()) {
274+
System.out.printf("Column %s has type %s%n",
275+
definition.getName(),
276+
definition.getType());
277+
}
278+
```
279+
280+
281+
### More information
5282

6283
If you're reading this from the [generated HTML documentation on
7-
github.io](http://datastax.github.io/java-driver/), use the "Read More"
8-
menu on the right hand side. If you're [browsing the source files on
284+
github.io](http://datastax.github.io/java-driver/), use the "Contents"
285+
menu on the left hand side to navigate sub-sections. If you're [browsing the source files on
9286
github.com](https://github.com/datastax/java-driver/tree/3.0/manual),
10287
simply navigate to each sub-directory.
11288

12-
This is a work in progress: new sections will be added to cover existing
13-
features or document new ones.
14-
15-
You can also find more help in the legacy
16-
[user documentation](http://docs.datastax.com/en/developer/java-driver/2.1/java-driver/whatsNew2.html)
17-
on the DataStax website.
289+
[Cluster]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Cluster.html
290+
[Cluster.Builder]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Cluster.Builder.html
291+
[Initializer]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Cluster.Initializer.html
292+
[Session]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Session.html
293+
[ResultSet]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/ResultSet.html
294+
[Row]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Row.html
295+
[NettyOptions]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/NettyOptions.html
296+
[QueryOptions]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/QueryOptions.html
297+
[SocketOptions]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/SocketOptions.html
298+
[Host.StateListener]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Host.StateListener.html
299+
[LatencyTracker]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/LatencyTracker.html
300+
[SchemaChangeListener]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/SchemaChangeListener.html
301+
[NoHostAvailableException]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/exceptions/NoHostAvailableException.html
302+
[LocalDate]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/LocalDate.html

manual/async/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,6 @@ There are still a few places where the driver will block internally
145145
hasn't been fetched already.
146146

147147
[ListenableFuture]: https://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained
148-
[init]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/Cluster.html#init()
149-
[setPoolTimeoutMillis]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/PoolingOptions.html#setPoolTimeoutMillis(int)
150-
[query trace]: http://docs.datastax.com/en/drivers/java/2.1/com/datastax/driver/core/QueryTrace.html
148+
[init]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/Cluster.html#init()
149+
[setPoolTimeoutMillis]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/PoolingOptions.html#setPoolTimeoutMillis(int)
150+
[query trace]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/QueryTrace.html

manual/auth/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## Authentication
2+
3+
*Coming soon... In the meantime, see the javadoc for [AuthProvider].*
4+
5+
[AuthProvider]: http://docs.datastax.com/en/drivers/java/3.0/com/datastax/driver/core/AuthProvider.html
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## Control connection
2+
3+
*Coming soon...*
4+
5+
<!--
6+
TODO cover:
7+
- what the control connection is (link to init sequence in ../README.md)
8+
- server-sent events (gossip + schema changes)
9+
- maybe event debouncing (although it sometimes applies to other types of events)
10+
-->

0 commit comments

Comments
 (0)