views:

505

answers:

3

I am trying to get a string of length 15 to be used as primary key in database tables. The following code in java returns some key with length 35

UUID.randomUUID().toString()
  1. Can I change it to return a key of the length 15 ?
  2. How to ensure thread safety?

Any help is greatly appreciated.

+1  A: 

Why don't you make use of Oracle's sequence facility? You can't do anything better/safer using Java.

Edit: Your main concern is thus database performance. You didn't want to connect "again" to get the generated ID from the database. This concern is not needed if you just make use of connection pooling and just reuse the same connection to obtain the generated key immediately. Most JDBC drivers can give you the generated key back by Statement#getGeneratedKeys(). The newer JDBC drivers of Oracle supports it.

Here's a basic example:

Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet generatedKeys = null;

try {
    connection = database.getConnection();
    preparedStatement = connection.prepareStatement("INSERT INTO user (name, age) VALUES (?, ?)";
    preparedStatement.setString(user.getName());
    preparedStatement.setInteger(user.getAge());
    int affectedRows = preparedStatement.executeUpdate();
    if (affectedRows == 0) {
        throw new DAOException("Creating user failed, no rows affected.");
    }
    generatedKeys = preparedStatement.getGeneratedKeys();
    if (generatedKeys.next()) {
        user.setId(generatedKeys.getLong(1)); // Here's the magic.
    } else {
        throw new DAOException("Creating user failed, no generated key obtained.");
    }
} catch (SQLException e) {
    throw new DAOException(e);
} finally {
    close(connection, preparedStatement, generatedKeys);
}
BalusC
Sequences can be reset, deliberately or accidentally, leading to key violations. Randomised UUIDs will never clash, however.
skaffman
I am setting the primary key value in my java app, to use oracle sequence I will need to connect to DB which is a bit overhead for me as we are chasing performance issues. I am looking for some thing like UUID but with length 15
Ravi Gupta
That's true, but I wouldn't tight-couple the control of the PK that much. The DB is now unportable. However, the final/right answer also depends on the context of the question, I've asked the OP for clarification.
BalusC
@Ravi: Oracle can automatically increment the sequence on insert, did you know that?
BalusC
@Ravi: connecting is indeed expensive, but with a connection pool you will already greatly improve connecting performance. Further on Oracle can auto-increment the sequence on every insert. You can reuse the same statement (and connection) to obtain the new sequence value so that you can pass it through in the Java code.
BalusC
A: 

randomUUID() does not create a real UUID (based on time, node, etc) but a pseudo random value. Assuming, the randomness is sufficiant, you should be able to pick any 15 chars from the 35 char UUID to create a random number - less strong compared to UUID but maybe sufficiant.

To really prevent clashes, you will need to maintain a sequence generator. If you don't want to use oracle, maybe a file based sequence generator is sufficiant? (next available sequence number is stored in a configuration file before it is used)

Andreas_D
OK - you prevent clashes for the first 10^15-1 records only, but I think, that not to bad for a start ;)
Andreas_D
A: 

If you really need to generate your own keys, you could try JUG. You specifically asked for strings of length 15 - JUG cannot give you this. I'm not sure why this matters so assuming all you really care about is uniqueness, UUIDs are 128-bit (if I remember right) and are displayed in hexadecimal when string formatted.

monorailkitty