Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto generate unique random string in Spring MVC + Hibernate

Background

I'm writing a project using Spring MVC (Framework v4.0.6.RELEASE, JPA v1.6.2.RELEASE) and Hibernate (Core v4.3.6.FINAL, JPA API v2.1). In my project, there are entities called 'Project'. Each of these projects have their unique, auto-generated IDs as primary keys. This ID is generated by the following code:

@Id
@Column(name = "project_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long projectId;

This code works as expected and automatically creates unique IDs.

Problem

Each of these projects are supposed to have a random, unique1 'secret' String, just like those assigned by API providers like Facebook, Twitter, etc. So, to achieve this, I tried using the following code, as per the Hibernate docs:

@Column(name = "project_secret", nullable = false, unique = true)
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
@GeneratedValue(generator = "uuid-gen")
private String projectSecret;

However, whenever I try to create a new project entity, I'm greeted by a org.springframework.dao.DataIntegrityViolationException with root cause:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
Column 'project_secret' cannot be null

This should be auto-generated by Hibernate on creation, must be random and unique1. A 128-bit UUID is enough for me (32 characters w/out dashes) and I read that Hibernate has a UUID generator, so that's what I was aiming to use.

Further Info

After searching for hours, I'm no closer to solving it the way I want to do it. I found one possible solution, which is to include:

@PrePersist
private void generateSecret(){
    this.setProjectSecret(UUID.randomUUID().toString());
}

in the Project entity class. When this method is inserted (and @GenericGenerator & @GeneratedValue tags removed), the project secret is correctly generated and inserted; system works as expected; no exceptions are thrown. However, (I believe) this can't ensure uniqueness2 and just causes an exception when a duplicate secret is inserted. I want to ensure uniqueness and preferably want to solve this with built-in Hibernate generators.

(Notes)

  1. I actually am not sure if uniqueness should be enforced. I suppose having every secret unique can (theoretically) create an additional layer of security, which takes me to:
  2. I realise that the probability of UUID collision is very very low, so UUID generation ensures that uniqueness in a probabilistic sense but can (or should) I be really sure of it?
like image 730
aemreunal Avatar asked Sep 30 '22 04:09

aemreunal


1 Answers

I had an issue like this before and I realised after a while that it was my database table that was causing the issue. This might be the same problem you are having...

For your project_id ensure you use the following when you are creating that column in the database

GENERATED ALWAYS AS IDENTITY

I hope this is the same issue and that this will be of help to you. Also would recommend using uuid2 as your strategy.

see here... http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#d0e5294

Edit

After realising that project_secret is not the @id field then the answer is that hibernate does not support generated values on any column except for the @id field. See here for more details : Hibernate JPA Sequence (non-Id)

like image 177
dectarin Avatar answered Oct 03 '22 08:10

dectarin