How does jpa annotation sequenceGenerator works and how to avoid duplicate entries? - spring

#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqGen")
#SequenceGenerator(name = "seqGen", sequenceName = "seq", initialValue = 1)
private Long id;
Basically, i have three entities (fetched at the same times) that share the same sequenceName in my database.
I know for performance purpose, it's better to use the same tab for every entities with a SequenceGenerator.
When fetching a lot of datas, sometimes, i have a duplicate entries error, and basically changing the next_val of my sequence fix the problem temporarly.
I want to know how the SequenceGenerator work better and if there is a work around this issue ?
EDIT : could you explain me better what exactly is the purpose of a sequence and how his algorithm works ?
EDIT 2 : in a post, i saw this comment :
"Assume that you create a sequence object that has the CACHE option
enabled in Microsoft SQL Server 2012 or SQL Server 2014. When the
instance is under memory pressure, and multiple concurrent connections
request sequence values from the same sequence object, duplicate
sequence values may be generated. In addition, a unique or primary key
(PK) violation error occurs when the duplicate sequence value is
inserted into a table."
Is there a link with my current issue ?

There is no algorithm for sequence, it is +1 similar to autoincrement, also it has nothing to do with fetching your data that has duplicate entries.
Duplicate entries only mean that your database or code has a bad structure which leads to allowing data to be duplicated in the first place.
GenerationType. IDENTITY − In identity, the database is responsible to auto-generate the primary key. Insert a row without specifying a value for the ID and after inserting the row, ask the database for the last generated ID. Oracle 11g does not support an identity key generator. This feature is supported in Oracle 12c.
GenerationType. SEQUENCE − In sequence, we first ask the database for the next set of the sequence then we insert a row with return sequence id.
https://www.baeldung.com/hibernate-identifiers

Related

How to create a serial numbers autogenerated in dynamoDb using annotations

I have created a pojo class in my java spring boot app and with respective annotations for doing create/update it's working fine but when i use the autogenerated key annotation it is creating some random id but i want those id column as serial numbers. Below i have given the annotations of my pojo class
#DynamoDBHashKey(attributeName = "id")
#DynamoDBAutoGeneratedKey
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
Generated random Id example
5d2af735-62ce-47d4-85bf-8beece056eb
How to generate the autogenerated column with serial numbers like we do in SQL autoincrement identity column?
No you cannot use DynamoDBAutoGeneratedKey to generate a incremented sequence,it is used to generate a random UUID.
The key generated in your case "5d2af735-62ce-47d4-85bf-8beece056eb" is standard UUID format which will help to scale and spread the data across the key space.
https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html
If you want to generate a incremental sequence what you can do is create a SQL table "sequence_table", which will have only 1 column as "sequence_id" which is set to auto increment.
Whenever you want to insert data to Dynamo you can first insert in the SQL sequence table and get the latest id.Using this id you can create a new Dynamodb entry. If the annotation DynamoDBAutoGeneratedKey is not used , you can use your own custom key value.Whenever multiple process try to add a new sequence to the sequence_table, each process will first take a lock on the table and then it will insert a new id. So this solution will work in case of distributed system as well.
However on a side note if your business logic does not care about the sequence of id, you should go with UUID only as it is highly scalable , as it is not recommended to have an integer which increments by 1 to generate a hash key of the table. In order for the table to scale according to the provisioned capacity, requests should spread evenly across the shards.
As keys adjacent in a sequence will be stored in the same partition space.
Also as one might expect new users to be more active than very old users, and so we would be gearing load towards whichever partition serves the newest user rows.

Use of Hibernate when constraints are not defined

We have a requirement to redesign one application but without doing any modification on the database.
The current code uses plain jdbc to query data. We are planning to implement hibernate instead as part of the redesign.
The problem is the current database doesn't have any constraints present at the database level.
For example if there are two entities Course and Review. The current database doesn't have any mapping between them.
Now in this case if I implement hibernate and try to have #OneToMany between Course and Review, without having those constraints in the database, will that work out fine?
1 To stop hibernate from changing you scheme set parameter
spring.jpa.hibernate.ddl-auto = none
81.2 Initialize a Database Using Hibernate
2 Set GeneratedValue strategies to use existing sequences
#SequenceGenerator(name="my_seq", sequenceName="my_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq")
private Long id;
This way Hibernate will change nothing in your schema. It will not create any sequences, tables, foreign keys, constraints e.t.c. Just use existing structure and fall if something wrong with it )
If there is no cascading from Course to Reviews and you delete Course the delete will go through without any complaints. With constraint present, DB would have complained about existing child records(Review in this case).
So special care needs to be taken specifying the cascade.

How to stop a user from entering duplicate values

In one of my Java EE applications, I used a registration page to register new user and as soon as one registers, his/her registered values will be inserted into Oracle database. But there is no way of detecting duplicate values. So I thought about adding unique constraint to some column values. But later I learned, I can't declare more than one column as unique( In my case I already declared userid as primary key). But I need to make more than one column values unique (like emialid field). Again only adding unique can't help as if a user submits a form with duplicate value an exception will be caught and user won't be able to understand as he will be redirected to a blank page. So I have 2 questions.
1) How can I inform the user about inserting duplicate values?
and
2) How can I make more than one column unique in Oracle?
N.B. I don't know javascript!!
First, you certainly can declare multiple unique constraints on a table. You can declare that userid is a primary key and then declare emailid as unique. You can declare as many unique constraints as you'd like.
Second, your application would need to catch the duplicate key constraint and do something useful with it. Redirecting the user to a blank page would not be useful-- your application ought to catch the constraint exception and present a useful message to the user. For example, if you get an exception stating that the constraint UK_EMAILID was violated, you'd probably want to present an error message to the user saying something along the lines of "This email address already exists."
If you are using JPA, you can build a unique constraints :
#Entity
#Table(name = "entity_table_name", uniqueConstraints={
#UniqueConstraint(columnNames={"uniqueField1"}), // Unique value on one field.
#UniqueConstraint(columnNames={"uniqueField2", "uniqueField3"}) // Unique combination.
})
public class YourEntity {
private Long id;
private String uniqueField1;
private String uniqueField2;
private String uniqueField3;
private String uniqueField4;
// ...
}
The implementation (hibernate, eclipseLink) will take care of the oracle part.

SQL Azure and Membership Provider Tenant ID

What might be a good way to introduce BIGINT into the ASP.NET Membership functionality to reference users uniquely and to use that BIGINT field as a tenant_id? It would be perfect to keep the existing functionality generating UserIds in the form of GUIDs and not to implement a membership provider from ground zero. Since application will be running on multiple servers, the BIGINT tenant_id must be unique and it should not depend on some central authority generating these IDs. It will be easy to use these tenant_id with a SPLIT AT command down the road which will allow bucketing users into new federated members. Any thoughts on this?
Thanks
You can use bigint. But you may have to modify all stored procedures that rely on user ID. Making ID global unique is usually not a problem. As long as the ID is the primary key, database will force it to be unique. Otherwise you will get errors when inserting new data (in that case, you can modify ID and retry).
So the most important difference is you may need to modify stored procedures. You have a choice here. If you use GUID, you don't need to do anything. But it may be difficult to predict how to split the federation to balance queries. As pointed out in another thread (http://stackoverflow.com/questions/10885768/sql-azure-split-on-uniqueidentifier-guid/10890552#comment14211028_10890552), you can sort existing data at the mid point. But you don't know future data will be inserted in which federation. There's a potential risk that federations will become unbalanced, and you may need to merge and split them at a regular interval to keep them in shape.
By using bigint, you have better control over the key. For example, you have two federations. The first has ID from 1 to 10000, and the second has ID from 10001 to 20000. When creating a new user, you first check how many records are in each federation. Suppose federation 1 has 500 records and federation 2 has 1000 records, to balance the load, you choose to insert to federation 1, so you choose an ID between 1 and 10000. But using bigint, you may need to do more work to modify stored procedures.

Castle ActiveRecord Seeding Primary Key Value

I am wondering how to 'seed' an auto incrementing primary key value using Castle AR? For Example wanting the Orders table primary keys to start out as 10000. Is this something that is 1. possible 2. a good solution for creating order numbers?
Maybe there is a way to have consecutive auto incrementing field on the DB that is NOT the pk, seeded to 10000?
Castle ActiveRecord is built on top of NHibernate and features of AR heavily rely on features of NHibernate. NHibernate contains several primary key generators:
1. native - This is the default generator. If you specify this then NHibernate automatically chooses generator type based on underlying database. For example, if I would have used native instead of identity in the above mapping snippet you will still get the same SQL because NHibernate is smart enough to understand that the underlying database SQL Server and it supports identity columns. NHibernate converts the returned values using Convert.ChangeType method.
2. identity - This can be used with Identity columns provided with SQL Server, MySQL, Sybase etc.,
3. sequence - Firebird, DB2, PostgreSQL, Oracle, SAP DB supports sequences
4. increment - This generator does not uses any database feature like sequence or identity. NHibernate automatically increments 1 to last primary key value. This generator is helpful when dealing with single database system but it does not help in cluster based environment.
5. hilo - Hi/Lo algorithm is used to generate primary key values. This is very efficient when compared to other generator types. When used, NHibernate creates a separate table named hibernate_unique_key and creates a column named next_hi and then NHibernate uses this table as a reference when INSERT happens. We will talk elaborately on this later in this post.
6. uuid.hex - Uses System.Guid and its ToString method for generating string based primary key values.
7. guid - This can be used when the class property type is Guid.
8. guid.comb - This is similar as guid but uses a different algorithm to produce primary key values. Note that uuid.hex, guid, guid.comb uses UNIQUEIDENTIFIER as a column data type in SQL Server.
9. assigned - last but not least, this generator assumes that the primary key value is assigned by the user.
So you can see that there are no such build-in functionality. In order to create an order number you can use 2 ways:
1. select max order and manually set it
2. add some insert trigger to database
In my opinion you should use first way because in this way you will not rely on database. And you can reuse this functionality when you will need to move an object up or down. I'm usually using this way.

Resources