Spring boot Hibernate Envers Audited customization - spring-boot

I have below entity class
class Emp {
private long id;
private String name;
private int salary;
}
for these class need audit table as below, which contains 1 extra column parent_id whose value will be primary key of emp table
ex audit table column
id(primary key), parent_id (Primary key of emp), rev, revtstmp, name, salary

Related

Spring Data JPA (Postgres) - Insert into One table, reading the foreign key from a table that contains static data

I am currently working with Spring Data JPA, specifically Postgres. Our database is highly Normalized. In some scenarios we have some tables that contains static data. In that case if I am going to insert into table address for example and table address_type contains the static data, I would need to insert the Primary Key of table address_type in a column of table address, to make a Foreign Key reference from table address to table address_type(static data).
Example:
Database Code
create table address_type(
id Serial Primary Key,
type char(3),
description (100)
);
insert into address_type(id, type, description) values(1, 'PRIMARY', 'Primary description');
insert into address_type(id, type, description) values(2, 'SECONDARY', 'Secondary description');
Relation (1 - N)
create table address(
id Serial Primary Key,
address varchar(50) not null,
address_type_id integer references address_type(id)
);
insert into address(id, address, address_type) values(1, 'address somewhere 1', 1);
insert into address(id, address, address_type) values(2, 'address somewhere 2', 1);
insert into address(id, address, address_type) values(3, 'address somewhere 3', 2);
Spring Data JPA Code
#Table(name = "address_type")
public class AddressType {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "type")
private String type;
#Column(name = "description")
private String description;
#OneToMany(mappedBy = "addressType")
private Address address;
// Getters and Setters (Lombok)
}
#Table(name = "address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "type")
private String address;
#Column(name = "address_type_id")
#JoinColumn(---> logic?????????? <-----)
#ManyToOne(---> logic?????????? <-----)
private AddressType addressType;
// Getters and Setters (Lombok)
}
I guess my question is how should I need to setup the logic inside the #JoinColumn and #ManyToOne annotations in the Address entity?
P.D. The Insert should only happen in table address, Spring Data should only read from table address_type to get the foreign key to be stored in the address table.
I got the answer after a lot of research and try/error.
The configuration inside the annotations are the following:
In class Address
#Column(name = "address_type_id")
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "address_type_id", referencedColumnName = "id")
private AddressType addressType;
Then in AddressType, you should always have a mapped by reference to the child table.
#OneToMany(mappedBy = "addressType")
private Address address;
One IMPORTANT thing to remember, is that before saving back to the database, you should fetch in the database for the entity you want to refer in your child table, so that Spring Data JPA recognize that this is NOT a new record in AddressType table, BUT just a reference and saves the foreign key in the Address table.

Spring Data JPA + Postgres - Unable to insert data with One to One mapping

I have a UserInfo and AddressInfo entity classes and they have one to one association. UserInfo uses sequence to add primary key but I am getting below error;
org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property
UserInfo Entity
#Entity
#Table(name = "userinfo")
public class UserInfo {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userid_seq")
#SequenceGenerator(name="userid_seq", allocationSize=1)
private Long userId;
private String firstName;
private String lastName;
private String email;
private String username;
private String password;
#OneToOne(mappedBy = "userInfo", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private AddressInfo addressInfo;
//Getters - Setters
}
AddressInfo Entity
#Entity
#Table(name = "addressinfo")
public class AddressInfo {
#Id
private Long addressId;
private String homeAddress;
private String homeCity;
private String homeState;
private String homeZip;
#OneToOne
#MapsId
#JoinColumn(name = "address_id")
private UserInfo userInfo;
//Getters - Setters
}
UserInfo Table
CREATE TABLE userinfo (
user_id INTEGER NOT NULL DEFAULT nextval('userid_seq') PRIMARY KEY ,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
username VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL
);
AddressInfo Table
CREATE TABLE addressinfo (
address_id INTEGER NOT NULL PRIMARY KEY,
home_address VARCHAR(100) NULL,
home_city VARCHAR(100) NULL,
home_state VARCHAR(100) NULL,
home_zip VARCHAR(100) NULL,
CONSTRAINT fk_addinfo
FOREIGN KEY(address_id)
REFERENCES userinfo(user_id)
);
I thought my sequence had some issues but I could see that if I remove the child entity then its is inserting into the UserInfo table successfully but getting above error when I add OneToOne mapping. Seems like I have issues with my Primary key. I see similar questions but I could not find what is going on here. A help would be really appreciated.
Two solutions come to mind:
A single transaction that inserts both Userinfo and Addressinfo. With the second insert using the sequence currval to define the id.
create table addressinfo (
address_id integer default currval('userid_seq') primary key,
home_address varchar(100) null,
home_city varchar(100) null,
home_state varchar(100) null,
home_zip varchar(100) null,
constraint fk_addinfo
foreign key(address_id)
references userinfo(user_id)
);
do $$
begin
insert into userinfo (first_name, last_name, email, username, password)
values ('Jane','Smith','j.smith#thisplace.org','js','psojHvIEJNB');
insert into addressinfo( home_address, home_city, home_state,home_zip)
values ('1 Joe''s Lane','Smithtown', 'NV', '0123456789asdfgh');
end;
$$;
A single statement handling the insert for both tables:
with newuser (user_id) as
(insert into userinfo (first_name, last_name, email, username, password)
values ('Joe','Smith','j.s.smith#thisplace.org','js2','+949+fsrgwDGKJS58')
returning user_id
) --select id from newuser;
insert into addressinfo(address_id, home_address, home_city, home_state,home_zip)
select user_id,'1 Joe''s Lane','Smithtown', 'NV', '0123456789asdfgh'
from newuser;
However neither is a good plan. A 1:1 relationships are always questionable. In this case they are not. What happens when user Jane Smith stores her address, then insists that her husband, Joe, have the same address. You wind up with DUPLICATE addresses. See example here. You might be better off giving addressinfo its own PK sequence and putting address_id as a column and FK into userinfo

Customize Spring boot ORM table column name

I am using Spring JPA. There is a class for JPA enitity
#Entity
#Table(name = SchemaConstant.MENU_TABLE)
public class Menu extends BaseEntity {
#NotNull private String title;
private String path;
private UUID parentId;
private boolean hasSub;
private String iconName;
}
And the snapshot of the database table columns are shown below
If you see the table columns order is not the same as the class order. Now I want to reorder this table's columns.
Like column 1 -> id, column 2 -> title, column 3 -> icon_name as requires
Is there any way of customizing the order of the table columns?

Spring JPA query for many to many

I have an entity User and System
#Entity
public class User {
private Long id;
private String name;
}
#Entity
public class System{
private Long id;
private Long SystemId;
#ManyToMany
private Set<User> users;
}
and one table created by hibernate legalhold_system
I want to get all the user related to System ID, I can fetch the same using below native query
select * from user where id in (select user_id from legalhold_system where system_id in(select id from system_user where system_id=:1))
How can I achieve the same with Spring JPA query, As I don't have legalhold_system entity present in Code?
If these are the only two entities, it should be doable using this query:
SELECT s.users FROM System s WHERE s.systemId = :systemId

JPA2 PrimaryKey vs Oracle Primary key

Is it possible that oracle table has a composite primary key oracle sequenceid +createtimestamp but the #Entity class we have just the #id (sequenceid) primary key ? Timestamp we are adding for the purpose of table partitions which we use for purging later. At the time of storing the entity we will add the timestamp value all the time. From the data point of view id alone is primary key for the record in this case. Can I create entity with primary key as id alone?
In this case you have to create composite primary key in # Entity class. You can as per below example
#Entity
#Table(name="RELEASE_PERSON")
#IdClass(ReleasePersonPK.class)
public class ReleasePerson implements Serializable {
#Column(name="ORDER_NO", nullable=false, precision=2)
private Integer orderNo;
#Id
#Column(name="RELEASE_ID", insertable=false,updatable=false)
private long releaseId;
#Id
#Column(name="PERSON_ID", insertable=false,updatable=false)
private long personId;
#ManyToOne
#JoinColumn(name = "PERSON_ID", referencedColumnName = "PERSON_ID")
private Person person;
#ManyToOne
#JoinColumn(name = "RELEASE_ID", referencedColumnName = "ID")
private Release release;
And your Id Class will be look like below
#Embeddable
public class ReleasePersonPK implements Serializable {
/**
*
*/
private static final long serialVersionUID = -6286499269052596345L;
private Person person;
private Release release;
In my example in ReleasePersone table we will have composite primary key from rRelease(ID) and Person (Person_id).
Let me know if you need anything else.
The answer is yes. as you said that the id will be unique in the table, it's definitely ok that just put sequenceId as PK in the entity. If you don't use hibernate to create the table or update the columns of table, it doesn't care what actually in the database.

Resources