Hot questions for Using Cassandra in uuid

Question:

I'm using Datastax Java driver to perform basic insert statement in Cassandra database. My primary key column is uuid type. From what I see in official documentation, recommended way to call uuid() function in Cassandra is to use QueryBuilder#uuid() method. However, is it safe to use java util's UUID.randomUUID() too, since my types are colliding (QueryBuilder.uuid() returns Object while UUID.randomUUID() returns UUID)?


Answer:

UUID.randomUUID() creates type-4 UUID and it is safe to use.

Infact, datastax UUID utility class com.datastax.driver.core.utils.UUIDs has a method named random(), which is just a convenience for UUID.randomUUID()

Question:

I'm currently working on a project that uses Cassandra/Solr, with a Java CRUD layer. SolrJ (at least the version that we're stuck with, doesn't play nicely with mapping Cassandra UUID or TimeUUID fields, so the recommendation that I've seen are to treat the UUID as a string in the POJO, and then let the getters and setters handle the conversion in and out.

Using toString() on the incoming UUID seems to work okay but, when we try to get the UUID back out from the string, we encounter problems. Using UUID.nameUUIDFromBytes(string.getBytes()) looked like it might be an answer, but that just gives us a generated UUID, based on the string, which totally breaks our primary key.

Has anyone encountered this? And, if so, did you find a solution?

Many thanks!


Answer:

What you are looking for is the static UUID.fromString(String name) method. It accepts the String representation created in the toString() method and creates the UUID.

Here is the link to the docs: https://docs.oracle.com/javase/7/docs/api/java/util/UUID.html

Question:

I have a question regarding UUID generation.

Typically, when I'm generating a UUID I will use a random or time based generation method.

HOWEVER, I'm migrating legacy data from MySQL over to a C* datastore and I need to change the legacy (auto-incrementing) integer IDs to UUIDS. Instead of creating another denormalized table with the legacy integer IDs as the primary key and all the data duplicated, I was wondering what folks thought about padding 0's onto the front of the integer ID to form a UUID. Example below.

*Something important to note is that the legacy IDs highest values will never top 1 million, so overflow isn't really an issue.

The idea would look like this:

Legacy ID: 123456 ---> UUID: 00000000-0000-0000-0000-000000123456

This would be done using some string concats and the UUID.fromString("00000000-0000-0000-0000-000000123456" method.

Does this seem like a bad pattern to anyone? I'm not a huge fan of the idea, gives me a bad taste in my mouth, but I don't have a technical reason for why haha.

As far as collisions go, the probability of a collision occurring is still ridiculously low. So I'm not worried about increasing collisions. I suppose it just seems like bad practice to me, that its "too easy".


Answer:

We faced the same kind of issue before when migrating from Oracle with ids generated by sequence to Cassandra with generated UUIDs.

We had to design a type to both support old data coming from Oracle with type long and new data with uuid.

The obvious solution is to use type blob to store the id. A blob can encode a long or an uuid.

This solution only works for partition key because you query them using =. It won't work for clustering column using operators like > or < because we need an ordering on their value.

There was a small objection at that time, which was using a blob to store the id makes it opaque to user, for example in cqlsh when you're doing a SELECT and you need to provide the id, how would you make a blob ?

Fortunately, the native functions of CQL bigIntAsBlob(), blobAsBigInt(), uuidAsBlob() and blobAsUUID() come in very handy.

Question:

I have a table with an ID field so defined:

create table XXX (
id uuid primary key,
name varchar,
....

and my class XXX is so annotated:

public class XXX {

@PrimaryKey
@Persistent(customValueStrategy = "uuid")
public UUID id;
...

When trying to issue a PersistenceManager.makePersistent(), I get:

Exception in thread "main" javax.jdo.JDOFatalInternalException: Invalid Id generated for field XXX.id, id : 54e5abde-732b-42ff-af92-06af89af46ff at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:673) at org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:720) at org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:740) at Importer.save(StayImporter.java:84) at Importer.exec(StayImporter.java:102) at Importer.main(Importer.java:110) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) NestedThrowablesStackTrace: Invalid Id generated for field XXX.id, id : 54e5abde-732b-42ff-af92-06af89af46ff org.datanucleus.exceptions.NucleusException: Invalid Id generated for field XXX.id, id : 54e5abde-732b-42ff-af92-06af89af46ff at org.datanucleus.store.AbstractStoreManager.getStrategyValue(AbstractStoreManager.java:1300) at org.datanucleus.state.StateManagerImpl.populateStrategyFields(StateManagerImpl.java:2201) at org.datanucleus.state.StateManagerImpl.initialiseForPersistentNew(StateManagerImpl.java:418) at org.datanucleus.state.StateManagerImpl.initialiseForPersistentNew(StateManagerImpl.java:120) at org.datanucleus.state.ObjectProviderFactoryImpl.newForPersistentNew(ObjectProviderFactoryImpl.java:218) at org.datanucleus.ExecutionContextImpl.persistObjectInternal(ExecutionContextImpl.java:2078) at org.datanucleus.ExecutionContextImpl.persistObjectWork(ExecutionContextImpl.java:1922) at org.datanucleus.ExecutionContextImpl.persistObject(ExecutionContextImpl.java:1777) at org.datanucleus.api.jdo.JDOPersistenceManager.jdoMakePersistent(JDOPersistenceManager.java:715) at org.datanucleus.api.jdo.JDOPersistenceManager.makePersistent(JDOPersistenceManager.java:740)

The UUID looks good to me, why does it not work?

Maven is:

<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-accessplatform-jdo-cassandra</artifactId>
<version>4.2.1</version>
<type>pom</type>
</dependency>

<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>2.1.9</version>
</dependency>

Cassandra version is 2.2.3


Answer:

See this forum post: http://www.datanucleus.org/servlet/forum/viewthread_thread,7922_lastpage,yes#lastpost

Excerpt from linked content:

"UUIDGenerator" generates Strings. Consequently you cannot currently use it to generate UUID values with released code. Nightly builds add support for converting a String generated value to any of TimeZone, Locale, UUID, Currency, so ought to work with that.

Barring that you can easily get the code and create your own ValueGenerator plugin that extends AbstractGenerator to generate UUID objects.