0

I am trying to create a custom ID for my Java Spring Boot project with format something like this BDI-100. I know how to setup the number part but have no idea how to put a prefix on it. I have tried a solution from this thread in stackoverflow but it seems like it can not match with my project because of some different versions with mine.

Here is the spec of my project:

  • built with Spring Tool Suite 4.18.0.RELEASE
  • Java 17
  • Spring Boot v3.1.3
  • Built on top of ubuntu 22.04

and this is my model class. Perhaps can give the clue. Thank you for any hand guys!

package com.recruittest.bosnet.model;

import java.util.Date;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

import com.fasterxml.jackson.annotation.JsonFormat;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;

@Entity
@Table(name = "bosnet_people")
public class People {

    @Id
    @Column(name = "people_id")
    @SequenceGenerator(name = "PeopleIdGenerator", initialValue = 100)
    @GeneratedValue(generator = "PeopleIdGenerator", strategy = GenerationType.IDENTITY)
    private String id;
    
    @Column(name = "full_name")
    private String fullName;
    
    @Column(name = "birthday")
    @JsonFormat(pattern = "yyyy-mm-dd")
    private Date birthday;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "People [id=" + id + ", fullName=" + fullName + ", birthday=" + birthday + "]";
    }
}

kaqqao
  • 12,984
  • 10
  • 64
  • 118
falah
  • 1
  • 3

1 Answers1

1

You need to create a CustomIdGenerator class that extends the IdentifierGenerator, this way:

public class CustomIdGenerator implements IdentifierGenerator {

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        String prefix = "BDI";
        String query = "SELECT MAX(people_id) FROM bosnet_people";
        Connection connection = session.getJdbcConnectionAccess().obtainConnection();

        try (PreparedStatement statement = connection.prepareStatement(query)) {
            ResultSet rs = statement.executeQuery();
            if (rs.next()) {
                String lastId = rs.getString(1);
                if (lastId != null) {
                    int number = Integer.parseInt(lastId.substring(prefix.length())) + 1;
                    return prefix + "-" + number;
                }
            }
        } catch (SQLException e) {
            throw new HibernateException("Unable to generate ID", e);
        }

        return prefix + "-" + 100; // Initial value if no records are present
    }
}

This generator will be responsible for generating the custom IDs.

Next, apply your custom ID generator to your People class:

@Entity
@Table(name = "bosnet_people")
public class People {

   @Id
   @GeneratedValue(generator = "custom-id", strategy = GenerationType.IDENTITY)
   @GenericGenerator(name = "custom-id", strategy = "your.package.here.CustomIdGenerator")
   @Column(name = "people_id")
   private String id;

   // ... other fields and methods
}

Check this out:

I hope it helps!

Diego Borba
  • 1,282
  • 8
  • 22
  • Hi, thanks for your response, it run without error. But for some reason, it doesn't auto generate `people_id` when I insert data into column `full_name` and `birthday`. The ID also must be manually inserted and it can accept any format in it. I also only can use this `Connection conn = (Connection) session.getJdbcConnectionAccess();` instead of this `Connection connection = session.connection();` because I can't find `.connection()` from my version. What kind of `Connection` that you use here? Is it this one `import java.sql.Connection;`? – falah Aug 30 '23 at 03:40
  • 1) About the **Auto-Generation Issue** try to change the `GenerationType.IDENTITY` to `GenerationType.SEQUENCE`. 2) "*The ID also must be manually inserted and it can accept any format in it*", you should put it in the question, 'couse maybe you are into a [XY Problem](https://xyproblem.info/). 3) Yes, it is `java.sql.Connection`, and `session.getJdbcConnectionAccess()` is incorrect does not provide the same functionality as `session.connection()`. – Diego Borba Aug 30 '23 at 11:40
  • `GenerationType.SEQUENCE` doesn't work either. With that 2nd point you highlight I mean 'can only be,,' not 'must be..'. Checking at my Hibernate version, it is version 6.2.7 Final and turn out at this version `.connection()` is already deprecated since Hibernate 4. They replace it with this `session.doWork(new Work() {...})`. Will try to figure this out. Thanks by the hand anyway – falah Aug 30 '23 at 18:48
  • My fault about the `.connection()` I've forget to check the version. I updated my answer. – Diego Borba Aug 30 '23 at 18:55
  • About the 2 point, what I mean with [XY Problem](https://xyproblem.info/) is: You tried to create a `Generator` but if the id can be manually inserted, maybe a `Generator` ins't the best solution for you. – Diego Borba Aug 30 '23 at 18:57