Postgresql and Spring Roo Binding serial type for ID - spring

I am having trouble using the Postgresql serial type in Spring Roo. What I want is to have the an auto-incrementing id column which will work with the auto generated entity classes in Roo.
The Postgresql sequences, which are generated with the default way of doing things in Spring Roo, work fine within the spring application. But sometimes I have to manually insert rows in the database using sql. (the sequences dont seem to work properly when I do an INSERT INTO... statement). If I could use serial type, then manual INSERTS are easy.
For example I have an office entity and and employee entity. There is a many-to-one relationship between employees and offices.
Here is my class for the Office entity.
#RooJavaBean
#RooToString
#RooJpaActiveRecord
public class Office {
#Id
#Column(name="officeid", columnDefinition = "serial")
#Generated(GenerationTime.INSERT)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long officeid;
/**
* Office Name
*/
#NotNull
#Size(max = 100)
private String name;
}
While this does work when my test inserts an office record, it fails when an employee record is inserted since the officeid foreign key value is null. (I guess it needs to flush between the office insert and the employee insert, but the auto-generate tests dont seem to do that.)
So what is the proper annotations to use to tell Roo (and hibernate/jpa) to use the serial data type, and also to work properly with inserts and relationships within the spring application?

Roo generates default JPA annotations, you must customize and setup them as needed. Note Roo guarantees your changes won't be modified.

Related

Is using #Entity annotation in Spring boot JPA creates a table?

BACKGROUND
I am new to developing API in spring boot. I have this project wherein it is connected to an Oracle DB and PostgreSQL. The Oracle DB already have an existing tables and I need to fetch some data from multiple tables and send it back as a response. The Postgres DB is where I store the users data and other some data that doesn't need to be stored in the Oracle DB. I am currently using native queries.
The Account is an entity wherein I just marked one of the columns as the #Id (It is actually not an Id but it is unique for all accounts):
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class Account {
#Id
private String sampleProperty1;
private String sampleProperty2;
private String sampleProperty3;
private String sampleProperty4;
private String sampleProperty5;
}
Now I have a repository interface:
public interface IAccountRepository extends JpaRepository<Account, String> {
#Query(value = "SELECT * FROM TABLE(SAMPLE_PACKAGE.SAMPLE_FUNC_GETACCOUNTS(?1))", nativeQuery = true)
List<Account> getAllAccountsByClientNumber(String clientNumber);
}
I was able to fetch the data and JPA mapped the columns automatically to my entity. Basically I am creating an Entity (Spring boot) for the data in my Oracle DB where the only purpose of it is to map the data and send it back to the user.
QUESTIONS
Will this approach create a table in my Oracle DB? I checked the Oracle DB and there is no table. But I'm worried it might somehow create a table of ACCOUNT in the oracle DB when it is on production. If this might happen, how can I prevent it?
This scenario also applies to other functionality like fetching transaction history, creating transaction, updating the Account data that are all in the Oracle DB. Am I doing it just right or there is a better option?
Is creating an Entity without a corresponding table have a drawback in Spring boot?
Note
I know you might say that I should just use the Oracle DB and create entities based on the existing tables. But in the future of the API, it will not have a connection with the Oracle DB. I already tried using projections it was also good, but I still needed to create a Response model and mapped it then send it back to user and creating a unit tests using the projection is pretty long and it sucks haha
You can set the following property:
spring.jpa.hibernate.ddl-auto=update
update will update your database if database tables are already created and will create if database tables are not created.

Optimistic locking - session based locking

I have a question related to optimistic locking in Spring/Hibernate actually.
I have following scenario with typical REST application with SQL database.
User A enters page and reads data - version 0 of entity - GET request
User B enters page and reads data - version 0 of entity - GET request
User A saves data - version 1 of entity - PUT request
User B wants to save data (PUT request), but I should see optimistic lock exception
Now my question:
Where hibernate saves data about entity version? I understand the situation when everything is in the same transaction:
Load data
Someone changed entity in the different transaction
Save data
But in my situation version will vanish GET and PUT are in totally different transaction/threads etc.
In my opinion I should save somewhere version loaded by the user to have correlation between GET and PUT requests e.g. in HTTP session or just return version in the response and then send that version in the PUT request.
Can it be done in the better way? Like out of the box?
JPA/Hibernate have #Version column in entity definition to check optimistic or pessimistic lockings. JPA/Hibernate saves versions in the table. For example you have Country table in db:
CREATE TABLE country (
id BIGINT NOT NULL AUTO_INCREMENT,
version BIGINT DEFAULT 0,
...
);
And Country entity:
#Entity
#Table(name = "country")
public class Country implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Version
#Column(name = "version")
private Long version;
...
}
If you update the country entity instances with optimistic lock conflicts, you get OptimisticLockException in JPA. You don't need to manage the versions, JPA/Hibernate checks the versions of entity instances for you.
Update for different transactions:
In different transactions you can get OptimisticLockException too because JPA/Hibernate checks in every update the version columns with database table. As long as you save your changes (commit), another changes of entity versions will be checked, doesn't matter whether in the same transaction or different transaction. Better you can manage your transactions with #Transactional annotation in Spring framework.

I am using Spring boot jpa with Restful api services to insert multiple users in array or list

As I am new to Spring boot. I am not at all clear about mappings. By using #Onetomany mapping in one entity and #manytoOne mapping at other entities. Using the controller I have to write REST API functions to insert multiple users at a time inside an array or set. Can anyone please suggest some websites or provide some existing codes?
The #OneToMany and #ManyToOne mappings can be used according to your use-case, whether you need bi-directional mappping or not. For a simple example consider the following :
#Entity
#Table(name="ENTITY_A")
public class EntityA{
//...
#OneToMany(mappedBy="EntityA")
private Set<EntityB> entityBItems;
// getters and setters
}
#Entity
#Table(name="ENTITY_B")
public class EntityB{
//...
#ManyToOne
#JoinColumn(name="entityA_id", nullable=false)
private EntityA entityA;
public EntityB() {}
// getters and setters
}
What you need to look out for is the owning side of the relation indicated by the mappedBy . The owning entity can be used to persist and get the data from the database. But from the description in your question I cannot understand whether you actually need to use mappings at all as you just have to insert multiple users into a table without any relations to another entity. It will be more helpful if you could explain more about your use case and provide code samples for furthur analysis.
For details about the mappings article or article .
Official doc .
MappedBy signals hibernate that the owner of key (relationship) is on the other side.
This means that although you link 2 tables together, only 1 of those tables has a foreign key constraint to the other one.
MappedBy allows you to still link from the table not containing the constraint to the other table.
If you still want use #JoinColumn on both the Entities you can use #JsonManagedReference and #JsonBackReference from com.fasterxml.jackson
To save the multiple records at same time you can use yourRepository.saveAll(entities)

How to manage unique Ids with Hibernate and Flyway?

Here is a snippet of my entity class
#Entity
public class User {
#Id
#GeneratedValue
private long id;
private String firstName;
private String lastName;
When using (Spring Boot + Hibernate) Spring Boot setups schema automatically including sequences like one below
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
But I am using Flyway 5.0.7 to setup my schema. And in this case I get the error below, which means sequence is not getting created.
Sequence "HIBERNATE_SEQUENCE" not found; SQL statement
I was able to fix this by creating sequence using flyway script like below
create sequence HIBERNATE_SEQUENCE start with 1001;
But now this sequence is used to generate Ids for all entities which I do not want. I want each entity to have its separate sequence.
Is it possible to create sequences using Hibernate when using Flyway? Otherwise it is not practical to manually create sequences for all entities which can be in hundreds.
Any alternative approach to handle this?
Flyway is a DB migration tool, and it does not know of any DDL/DML changes unless you tell it so (via new scripts in the locations property).
If Hibernate handles some of these changes (the sequences in your case) Flyway won't know about it and will use whatever sequence it already has knowledge about.
The normal thing to do is letting Flyway know of your changes, which includes a new sequence for a new entity for instance, just like you would do for the schema itself of your entity. My personal advice is to manage all your schema changes in one place, so if you are using Flyway, then let it be in charge of all of it.

self referencing object in JPA

I am trying to save a SystemUser entity in JPA. I also want to save certain things like who created the SystemUser and who last modified the system User as well.
#ManyToOne(targetEntity = SystemUser.class)
#JoinColumn
private SystemUser userWhoCreated;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(iso=ISO.DATE_TIME)
private Date timeCreated;
#ManyToOne(targetEntity = SystemUser.class)
#JoinColumn
private SystemUser userWhoLastModified;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(iso=ISO.DATE_TIME)
private Date timeLastModified;
I also want to ensure that these values are not null when persisted. So If I use the NotNull JPA annotation, that is easily solved (along with reference to another entity)
The problem description is simple, I cannot save rootuser without having rootuser in the system if I am to use a DataLoader class to persist JPA entity. Every other later user can be easily persisted with userWhoModified as the "systemuser" , but systemuser it's self cannot be added in this scheme.
Is there a way so persist this first system user (I am thinking with SQL). This is a typical bootstrap (chicken or the egg) problem i suppose.
Have you tried rootUser.setUserWhoLastModified(rootUser) ?

Resources