I have a table of customers, each customer belongs to a company, companies want their customer numbers to start at 0 and increment as they add customers and when companyB adds a customer, companyA's customer numbers shouldn't be affected. CustomerId internally can be any number, customerNumber must be incremented gap-free in the context of the companyId (with gap-free I mean 0,1,2,3,4, if 2 is deleted, it's gone, the next insert should be 5 and not 2)
Example:
companyId customerNumber customerId
0 0 0
0 1 1
0 2 2
0 3 3
0 4 4
0 5 5
1 0 6
1 1 7
1 2 8
I was wondering if there's a better way to do it than opening a transaction, finding the max customerNumber, inserting an entry using the max+1 as customerNumber and closing transaction
Is there some sort of annotation I can use where I can specify the criteria for generating a customerNumber? The next customerNumber should be the highest number available within that company. (I have about 20 other entities that have similar human-readable-incremental-id requirements based on date and comapnyId and I want to make the customerNumber-type fields generation as fool-proof as possible, I don't want to have to remember to do it everytime I persist a new entity)
Something like:
@SequenceGenerator(uniqueOver="companyId,customerNumber",strategy=GenerationType.AUTO)
private Long customerNumber;
The solution should be ACID compliant since I'm working with stock and financial data.
Update: I've renamed id to customerId and customerId to customerNumber to prevent confusion.
Update: When I mean gap-free, I mean that customerNumbers should be 0,1,2,3,4,5,6,7,8,9 - if I delete number 4 it is gone forever and the next insert should be 10 unless I create a new company, then their first customer should start at 0.
Update: I'm using spring with hibernate, so the @PrePersist annotation is not working for me. If @PrePersist is suggested as a solution, then it needs to work under spring, so an answer for Simon's question would be needed: Enable @PrePersist and @PreUpdate in Spring
Suggested Answer which I'm not sure about:
@Entity
@Table(name = "Customer")
public class Customer {
@Table(name = "CustomerNumber")
@Entity(name = "sequenceIdentifier")
public static class CustomerNumberSequenceIdentifier {
@Id
@GenericGenerator(name = "sequence", strategy = "sequence", parameters = {
@org.hibernate.annotations.Parameter(name = "sequenceName", value = "sequence"),
@org.hibernate.annotations.Parameter(name = "allocationSize", value = "1"),
})
@GeneratedValue(generator = "sequence", strategy=GenerationType.SEQUENCE)
private Long id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long customerId;
@ManyToOne
private Company company;
@GeneratedValue(generator = "sequenceIdentifier", strategy=GenerationType.TABLE)
private Long customerNumber
}