Within JPA in Spring Boot / Spring Data, I want to set up an entity class.
The business requirement is to historize the processing of documents that exist once per year each.
The processing is performed in a bulk: so all documents are processed together: there is one processingTimestamp for all documents in the database for each processing sequence.
Later on, I want to access only the most recently processed document, but keep the previously processed documents for reference.
I see the following alternatives:
Use a composite key
#Id
private String documentId;
#Id
private String yearOfDocumentCreation;
#Id
private java.sql.Timestamp processingTimestamp;
Use an auto generated key
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String documentId;
private String yearOfDocumentCreation
private java.sql.Timestamp processingTimestamp;
Which alternative is better/best practise regarding
Handling (e.g. storing a list of documents as a bulk that were read before from the database and avoiding duplicates in the database)
Performance
Or do I miss other alternatives/aspects?
I recommend using a single Long primary key, if you will need to make a foreign key to this table.
To avoid dublicates you can make a unique constraint on the 3 required columns.
Related
I have a table which is of kind Ledger which records all information with no unique values.
Name
Date
Statement
First
row
random data
Second
row
random data
I am trying to create an Entity which will only fetch name and statement
#Entity
public class MyTable {
private String name;
private String statement;
}
As I am not specifing #Id I am getting exception and We don't have any unique identifier in the table I can't mention #Id annotation.
Also, If we need to write any user defined method for getting these values please suggest how to do that as well.Any sources or samples will greatly help here.
As you don't have any unique identifier, you need to define that first.
You can do it in two ways:
Redesign the table and identify any column which is unique Or
Declare a Long value as a unique identifier like this[works for mysql, for pg, you need to define a sequence for auto id generation]:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Moreover, to get values, don't forget to add getters setters method for these fields.
Method to store entity:
PoolDef poolDef = new PoolDef();
poolDef.setDate_from(date);
poolDef.setName(poolList.getPoolList().get(i).getName());
poolDefRepository.save(poolDef);
Entity itself:
#Setter
#Getter
#EqualsAndHashCode(of = {"Id"})
#Transactional
#Entity
public class PoolDef {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
private String name;
#Column(name = "date_from", columnDefinition = "timestamp with time zone not null")
private OffsetDateTime date_from;
}
The only value that varies is the date_from. I do not know, why new entries are being added to the database and not just get updated. I have the #EqualsAndHashcode that are being built based on primary Id key, so the date_from should not matter. Every method invocation creates a new entry with a completely new Id...
your problem is your
GenerationType.IDENTITY
the documentation says:
Indicates that the persistence provider must assign primary keys for
the entity using a database identity column.
Now the key question is, what SQL is getting generated. Can you please trace the insert SQLs generated?
Also I would prefer to use SEQUENCES of databases. So I do not have to mess around with the Identities of the persistence provider and any application will behave the same against the database if you use the SEQUENCES of databases for your ID/primary key columns.
Also a issue could be your DDL for the table creation, but I assume you know how to define the database tables with the given constraints.
I am using Spring with JPA and have 2 entities:
public class DocumentType {
#Id
#GeneratedValue
private Long id;
private String name;
private String idPrefix;
private Integer maxNumberOfSuffixDigits;
private Long startingSuffixNumber;
private String nextDocId;
...
}
public class Document {
#Id
private String id;
#ManyToOne
#JoinColumn
private DocumentType documentType;
...
}
Many Documents can be mapped to the same DocumentType, and there can be many DocumentTypes. The id for the Document will be generated using the combination of parameters found in it's corresponding DocumentType which is: idPrefix + startingSuffixNumber prefixed with 0s to meet the maxNumberOfSuffixDigits constraint. Currently I am on the fence of whether or not I will store the pre-generated nextDocId, but for the purposes of this question (if it makes the solution easier) let's assume that it is available.
The problem I have is getting the nextDocId, and generating the following Id in a concurrent environment. I've looked into Pessimistic write locks, but I do not think that can solve this issue, as from what I've seen, it only locks a single query. I need a way to somehow lock two queries: select query on the nextDocId, followed immediately by an update to generate a new nextDocId.
Any suggestions on how I can achieve this, or other alternatives to this problem would be greatly appreciated.
in JPA2 when we are using Embed-able (Basic Type like String.. etc ) object in Entity using with #ElementCollection and #CollectionTable annotation , the new table is created , but in new table how to declare primary-key contraint in column ? following is my code
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private String salary;
#Transient
private String phnNum;
#Enumerated(EnumType.STRING)
private EmployeeType type;
#ElementCollection
#CollectionTable(name="vacations" , joinColumns=#JoinColumn(name="Emp_Id"))
private Collection<Vacation> vacationBooking;
#ElementCollection
private Set<String> nickNames;
...................
with this code the "vacation" and "employee_nickname" two tables are created in schema. but i want to declare the one primary-key column in both table . what i do for this?
It looks like a primary key per se is not supported by JPA 2.0:
From Wikibooks:
The JPA 2.0 specification does not provide a way to define the Id in the Embeddable. However, to delete or update an element of the ElementCollection mapping, some unique key is normally required. Otherwise, on every update the JPA provider would need to delete everything from the CollectionTable for the Entity, and then insert the values back. So, the JPA provider will most likely assume that the combination of all of the fields in the Embeddable are unique, in combination with the foreign key (JoinColumn(s)). This however could be inefficient, or just not feasible if the Embeddable is big, or complex.
Some JPA providers may allow the Id to be specified in the Embeddable, to resolve this issue. Note in this case the Id only needs to be unique for the collection, not the table, as the foreign key is included. Some may also allow the unique option on the CollectionTable to be used for this. Otherwise, if your Embeddable is complex, you may consider making it an Entity and use a OneToMany instead.
Do you mean that you want to assign 'id' from Employee table as foreign key to the Vacation table?
In that case, you should use #OneToMany instead of #ElementCollection
It turns out that the following example works when using mysql 5.x, however it doesn't when using an oracle 10g database.
Is there a way to define a unique identifier field that is independent of the database technology?
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private long id;
I have tested this in hibernate and the following exception occurs only when using Oracle:
org.hibernate.MappingException: Dialect does not support identity key generation
Using a database table is a portable way to generate identifiers.
The simplest way to use a table to generate identifiers is to specify TABLE as the generation strategy:
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
#Column(name="id")
private long id;
The provider will create the default table if you're using schema generation; if not, you must specify an existing table:
#TableGenerator(name="InvTab",
table="ID_GEN",
pkColumnName="ID_NAME",
valueColumnName="ID_VAL",
pkColumnValue="INV_GEN")
#Id
#GeneratedValue(generator="InvTab")
#Column(name="id")
private long id;
http://www.oracle.com/technology/products/ias/toplink/jpa/howto/id-generation.html#table
I have researched using GenerationType.AUTO and it does appear to be the better option. It allows the JPA implementation to choose whatever is best for the data storage system you are using.