Grim
Grim

Reputation: 2097

Hibernate is generating duplicate primary keys while using uuid

I am having an issue where hibernate is storing the same keys multiple times. Example, lets say I have an object with the primary key as "stack overflow". I create another object with the same primary key "stack overflow", hibernate will save both objects and each object will have its own record. I personally believe this is caused by the uuid as "stack overflow" wouldn't appear in the database twice but the unique uuid of each object is different. How do I fix generating a different uuid for strings?

Users class, the email field works as expected and doesn't allow duplicate emails.

@Entity
@Table(name = "Users")
public class User {

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String username;

    @Column(unique = true)
    private String email;

    private String password;
    private String firstName;
    private String lastName;

    // Getters and Setters

Table Data

+--------------------------------------+-------------------------+-----------+----------+----------+
| username                             | email                   | firstName | lastName | password |
+--------------------------------------+-------------------------+-----------+----------+----------+
| 2afcb68b-e7e2-4b7d-bb8e-c886b34092aa | [email protected]         | charlie   | sexton   | sexton   |
| 365a64b0-e036-4654-ad3a-afe2440f5b37 | [email protected]           | charlie   | sexton   | sexton   |
| 9f9c89f5-7fba-4600-bb86-951c64d9988e | [email protected] | charlie   | sexton   | sexton   |
| a27c5ab7-c651-4027-8a89-0eb516930b31 | [email protected]         | charlie   | sexton   | sexton   |
| f7252552-f54b-453a-9806-2d2e4fd40f43 | [email protected]    | charlie   | sexton   | sexton   |
+--------------------------------------+-------------------------+-----------+----------+----------+

Code used to create the data....So the first three entries in the database are correct. So what I did was run the below code once to generate the first three records. Then to get the last two records I deleted session.save(user); and then changed the email address of user2 and user3 on the second run. I didn't touch the username field at all of user2 or user3 on the second run, why did hibernate allow this? I am relatively new to hibernate and couldn't find and resources. The Google God wasn't nice to me.

User user = new User();
user.setUsername("charles");
user.setPassword("sexton");
user.setFirstName("charlie");
user.setLastName("sexton");
user.setEmail("[email protected]");

User user2 = new User();
user2.setUsername("cs");
user2.setPassword("sexton");
user2.setFirstName("charlie");
user2.setLastName("sexton");
user2.setEmail("[email protected]");

User user3 = new User();
user3.setUsername("cs");
user3.setPassword("sexton");
user3.setFirstName("charlie");
user3.setLastName("sexton");
user3.setEmail("[email protected]");

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();

session.save(user);
session.save(user2);
session.save(user3);

List<Expense> listReport = query.list();

session.getTransaction().commit();

session.close();

Upvotes: 0

Views: 832

Answers (1)

Igoranze
Igoranze

Reputation: 1486

I think this is because you generate UUID's, instead of making a UUID from your username

I tested this with my code:

package nl.testing.startingpoint;

import java.io.IOException;
import java.util.UUID;

public class Main {

    public static void main(String args[]) throws IOException{
        String a = "stack Overflow";
        String b = "stack Overflow";

        System.out.println(UUID.nameUUIDFromBytes(a.getBytes()).toString());
        System.out.println(UUID.nameUUIDFromBytes(b.getBytes()).toString());

        System.out.println(UUID.nameUUIDFromBytes(a.getBytes()).toString());
        System.out.println(UUID.nameUUIDFromBytes(b.getBytes()).toString());
    }
}

and this is the result:

e6b8789f-8fac-3c40-94ae-6f2fe4b009fc
e6b8789f-8fac-3c40-94ae-6f2fe4b009fc
e6b8789f-8fac-3c40-94ae-6f2fe4b009fc
e6b8789f-8fac-3c40-94ae-6f2fe4b009fc

But because you use annotations with

@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")

The String username is overwritten with the generated UUID from hibernate. Instead, i think you should create a UUID from the string you are passing into the constructor.

NOTE: I did not test the latter, it's an assumption!

Upvotes: 1

Related Questions