How to define custom sequence generator used for Id (primary) in JPA? - jpa

My application is using JPA for persisting data to Database.
The application has to generate Custom(encoded) sequence for performance reasons.
By default JPA seems to generate Ids for an entity using some sequence.
How to override default sequence generator with customer sequence generator in Java ? I want to have sequence generator in Java as I have a separate logic for that.

This is how you go with the custom sequence:
#Id
#SequenceGenerator(name = "pet_seq",
sequenceName = "pet_sequence",
initialValue = 1, allocationSize = 20)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pet_seq")
#Column(name = "id", nullable = false)
private Long id;
In this case it will use pet_sequence instead of the default one. Also you can read this article for a better understanding of this subject.

Related

Alternative initial value for entity in JPA

I have the following entity and their mapping
#Entity
#Table(name = "test")
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator", initialValue = 20000)
I want id value begins in 20000 but it doesn't work in postgresql. When the application starts I receive this exception
Caused by: org.hibernate.HibernateException: Multiple references to
database sequence [sequence_generator] were encountered attempting to
set conflicting values for 'initial value'. Fou nd [20000] and [1]
Do I need a extra configuration to it works?
PS: It is a new database without any previous configuration
You could try #TableGenerator annotation. Initial values can be set and seed other values.
You can find example and documentation here:
Set Initial Value Of Table Generator

Spring JPA Entities: related problems of Ignite error, LAZY fetching, and too-m, minimizing database use and working with Ignite

I'm writing some entity relationships using Spring Data and Java. I have this pair of classes (edited):
Subject:
#Entity
#Table(name = "SUBJECT")
// Lombok, etc., attributes removed
public class Subject {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "ID", updatable = false, nullable = false)
#JsonProperty("id")
private Long id;
#OneToMany(targetEntity = SubjectResource.class, mappedBy = "subject", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<SubjectResource> resources;
}
SubjectResource:
#Entity
#Table(name = "SUBJECT_RESOURCE")
// Lombok, etc., attributes removed
public class SubjectResource {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "ID", updatable = false, nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "SUBJECT_ID")
private Subject subject;
}
I'm trying to solve these issues:
Question 1: Can I manipulate #OneToMany or #ManyToOne to NOT have the child class recurse its parent?
Fetch of resources returns subject data:
/subject/101:
{"id":101,"resources":[{"id":1001,"subject":101},{"id":1002,"subject":101},{"id":1003,"subject":101},{"id":1004,"subject":101}]}
/subjectResource/1001:
{id:1001,subject:{"id":101,"resources":[{"id":1001,"subject":101},{"id":1002,"subject":101},{"id":1003,"subject":101},{"id":1004,"subject":101}]}}
That is, /subjectResource/1001 returns its ID and the entire /subject/101 query.
How can I have just the subjectResource data, without its parent?
Question 2: Through #OneToMany or #ManyToOne can I get Hibernate to fetch on a "1" (O(1)) basis?
When /subjects does its thing, it works with Hibernate on a "n+1" (O(n)) basis: 1 fetch of subjects, n fetches of resources, one for each subject ID.
I could force a single fetch through a fancy repository #Query annotation ("select s from subject s left join fetch s.resources"). But that means putting the subject : subject_resource definitions in two places, etc.
Can JPA implementation / Hibernate be forced to do a join, and thus make only one database call, through annotation within an entity class?
Question 3: How do I get my Spring Data / Spring Repository to cooperate with Ignite, and have the cache return the data it already had on the first call?
I'm usng FetchType.LAZY, as all good pupils do. I'm also storing things in Apache Ignite. For /subject/101 the initial call fetches everything OK, returning it in JSON. But the second call gets from the Ignite cache, which complains about being out of transaction.
How do get my LAZY fetches to cooperate with Ignite?
Thanks,
Jerome.

How to make primary key value in each table should start from numeric One (1) - PostgreSQL , Spring data jpa

In my current project we are using PostgreSQL as DB and Spring data JPA for persistence. In all entity classes we are using GenerationType.SEQUENCE for generation of primary key value. It's working fine. But, the value for the primary key in each table not starting from 1 . The value is always next increment value of the maximum number of other table's primary key.
How can we change this ? . How to make primary key value of each table should start from 1.
You need to configure a sequence per table. This answer explains how to do that.
I'm just quoting it here:
Contents of my package-info.java:
#GenericGenerator(
name = "optimized-sequence",
strategy = "enhanced-sequence",
parameters = {
#Parameter(name="prefer_sequence_per_entity", value="true"),
#Parameter(name="optimizer", value="hilo"),
#Parameter(name="increment_size", value="50")})
package org.example.model;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
On the usage side you just need
#Id #GeneratedValue(generator="optimized-sequence")
public long id;
Below code on ID worked for me.
#Id
#SequenceGenerator(name = "MY_ENTITY_SEQ", sequenceName = "MY_ENTITY_SEQ", allocationSize=1)
#GeneratedValue(strategy = GenerationType.AUTO, generator = "MY_ENTITY_SEQ" )
#Column(updatable = false, nullable = false)
private Integer id;
Please let me know if i face any issues with this approach in future.

JPA: Usage of #GeneratedValue on non-id column

I am attempting to persist an entity with an attribute that I want to be populated from a DB sequence. I'm using Oracle, have created the sequence, verified the sequence works via sql, and yet my attribute isn't getting populated. Here's what I have:
#GeneratedValue(generator = "RFQ_LINE_IDS_SEQUENCE", strategy=GenerationType.SEQUENCE)
#SequenceGenerator(name="RFQ_LINE_IDS_SEQUENCE", sequenceName="RFQ_LINE_IDS_SEQUENCE", allocationSize=1000000000)
#Column(name = "external_line_item_id")
private String externalLineItemId;
All the examples I'm seen online show this annotation being used with #Id, but I have another attribute that I'm using for my id.
I've also tried the following to no avail:
#GeneratedValue(generator = "RFQ_LINE_IDS_SEQUENCE", strategy=GenerationType.SEQUENCE)
#GenericGenerator(name = "RFQ_LINE_IDS_SEQUENCE", strategy = "sequence",
parameters = {#Parameter(name = "sequence", value = "RFQ_LINE_IDS_SEQUENCE")})
#Column(name = "external_line_item_id")
private String externalLineItemId;
JPA only mandates support for #GeneratedValue on #Id fields. Some JPA implementations (such as DataNucleus JPA) support it but not all do.
I have created a proposal for JPA to support #GeneratedValue for non-id attributes. Please vote here for this to be included in 2.2
https://java.net/jira/browse/JPA_SPEC-113

EclipseLink sequential numbered ID's using GenerationType.Identity

Extending this question Why does eclipselink consume the whole allocationSize each time it's rebooted?
I would like to know what a proper solution for this problem is, the only answer in that post suggests switching to an IDENTITY strategy which i have done but i cannot see the changes. The allocation size of 50 is still in affect. Does anyone have any examples on how to generate sequential identifiers (1, 2, 3) based on each entity (table) and not a single sequence accessible by all tables?
You have the TableGenerator annotation for that purpose.
#Entity
public class Employee {
#Id
#TableGenerator(name="TABLE_GEN", table="SEQUENCE_TABLE", pkColumnName="SEQ_NAME",
valueColumnName="SEQ_COUNT", pkColumnValue="EMP_SEQ", allocationSize = 500, initialValue = 1)
#GeneratedValue(strategy=GenerationType.TABLE, generator="TABLE_GEN")
private long id;
...
}
#Entity
public class PaySlip {
#Id
#TableGenerator(name="SECOND_TABLE_GEN", table="SECOND_SEQUENCE_TABLE", pkColumnName="SEQ_NAME",
valueColumnName="SEQ_COUNT", pkColumnValue="SECOND_EMP_SEQ", allocationSize = 500, initialValue = 1)
#GeneratedValue(strategy=GenerationType.TABLE, generator="SECOND_TABLE_GEN")
private long id;
...
}
Make sure that all the name/*table* and pkColumnValue fields value are unique.
Reference
Sequence Strategies