EclipseLink 2.1.3, Oracle 11g, return PK after persist with container managed persistence - oracle

I'm using EclipseLink 2.1.3 with a container managed EntityManager to interface with an Oracle 11g DB.
I want to have an Entity's #Id variable updated immediately after I call persist() on the EM.
What is the correct strategy to do so with an Oracle DB?
None of the examples I've found on this site deal with this problem with container managed persistence.
The Entity looks like this:
#Entity
#Table(name = "ANNOUNCEMENT_DELIVERY_LOG")
public class AnnouncementDeliveryLog implements Serializable {
#Id
private BigDecimal id;
#ManyToOne
#JoinColumn(name = "ANNOUNCEMENT_ID ")
private Announcements announcement;
public AnnouncementDeliveryLog() {
}
}
Do I need to add something like the following?
#Column(nullable = false)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ANNOUNCEMENT_DELIVERY_LOG_SEQ")
#SequenceGenerator(name="ANNOUNCEMENT_DELIVERY_LOG_SEQ", sequenceName="ANNOUNCEMENT_DELIVERY_LOG_SEQ")
To persist the Entity I'm just calling persist(). Do I also need to call flush()?

Yes, you have to provide a #SequenceGenerator annotation in order that JPA automatically assigns a new ID to the entity during persist().
A flush is not necessary.

Related

Spring Data Persist entity in Log Table before each save()

im working in a spring boot project and i have a requirement to save the old object in a specific table before each new save ; this my man entities:
#Entity
#Table(name="demande")
public class Demande {
#Id
private Long id;
// all properties
}
#Entity
#Table(name="demande_log")
public class DemandeLog {
#Id
private Long id;
// all properties
}
what im trying to do is before each demandeRepository.save(demande);
i want to save the old demande object (current row in database) as DemandeLog in my demande_log table.
do you have any idea how using spring data, i know that there is a listener #PrePersist in JPA.. but i want to do it properly.
Regards.
I recommend using Envers. It is easy to set up and gives you a complete change log.

How to make #Indexed as unique property for Redis model using Spring JPA Repository?

I have a model class that I store in Redis and I use Jpa Repository with Spring java. Normally(not with redis) jpa repository is saving the new data or updates(conditionally) if the given model is already exist in Db. Here, I want to add new item to redis but if it is not already exists on db otherwise update it just like usual Jpa implementation.
Here is my model:
#Getter
#Setter
#RedisHash("MyRecord")
public class MyRecordRedisModel {
private String id;
#Id
#Indexed
private String recordName;
private Date startDate;
private Date endDate;
}
And my repository class is just a normal spring jpa repo as follows:
#Repository
public interface IFRecordRedisRepository extends JpaRepository<IFRecordRedisModel, String> {
Page<IFRecordRedisModel> findAll(Pageable pageable);
}
Unique key must be the name (I totally do not care about uniquiness of the id). Thus, if the name is already exist in Db than do not add it again. I marked it as Indexed but still it is adding same data (with same recordName).
How can I make it unique?
This would require an additional query, but I think this solution would work for you. You can use query by Example to check if there exists a record with that name, and save conditionally, or do something else if it already exists.
IFRecordRedisModel exampleRecord = new IFRecordRedisModel();
exampleRecord.setRecordName(inputRecord.getRecordName());
if (!repository.exists(Example.of(exampleModel)))
repository.save(inputRecord);
else ..... // do something else

Spring data jpa does not update existing row (Oracle) when using #sequencegenerator

New to spring data JPA. I have sequence created in oracle table. I am using JPARepository saveall() method to save the data. Inserts work without any problem but when i try to update any existing rows in the table it always tries to insert throwing unique constraint error since i have unique index created for that table.
Entity Class
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator1")
#SequenceGenerator(sequenceName = "emp_seq", name = "generator1",allocationSize = 1)
#Column(name = "USER_ID")
private Long id;
Save method invocation
public void persistEmployees(List<Employee> employees) {
employeeRepo.savaAll(employees);
}
Repository class
#Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> { }
How can i tell JPA to look for existing row before inserting? Any help is much appreciated!!!
In My Humble Opinion;
Using "Exists" condition-check as "sub-query" for all constrained columns, before Update will solve this.

Spring data #ReadOnlyProperty causing unexpected behavior

I have a Model attribute that needs to set #ReadOnlyProperty so that it won't persist after first inserting the line.
Assume my model like below
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(updatable = false, nullable = false)
#JsonIgnore
private Long id;
#Column(unique = true, nullable = false)
#ReadOnlyProperty
private String openId;
}
then I have a UserRepository:
public interface UserRepository extends JpaRepository<User, Long> {
}
then I provide 2 Restful API for POST and PUT.
The create user operation code is as simple as below:
user.setOpenId(1);
userRepository.save(user)
The update user operation is almost the same:
user.setOpenId(2);
user = userRepository.save(user);
I'm surprised that the user's openId attribute will be changed, after POST and then PUT, the returned user object will have the changed value.(user.getOpenId() == 2)
It looks like #ReadOnlyProperty not working, I'm using the RELEASE version of spring-boot-starter-data-jpa. Can someone help explain?
It seems that #ReadOnlyProperty doesn't work. The following bug report is open for years:
Properties with #ReadOnlyProperty annotation are being nullified in PATCH requests
If you want to deny modifying the property via Spring Data Rest endpoints, use the #JsonProperty(access = Access.READ_ONLY) annotation. It affects the JSON deserialization, so the annotated property never reaches Spring Data Rest.
If you also need to deny the writing of the property via Spring Data JPA, you can use the following JPA annotation: #Column(updatable=false) It denies the override on the underlaying JPA level, instead of Spring Data JPA level.

Get entity property with Spring JPA

I'm using Spring JPA in my DAO layer. I have an entity Projet having inside an entity property Client:
Project.java
#Entity
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int projetId;
private String libelle;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="client_id")
private Client client;
// ... constructors, getters & setters
}
Client.java
#Entity
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int clientId;
private String denomination;
// ... constructors, getters & setters
}
in my DAO interface I have the following specifications:
ProjetDao.java
#Repository
#Transactional
public interface ProjetDao extends CrudRepository<Projet, Integer> {
#Transactional
public Projet findByLibelle(String libelle);
#Transactional
public Projet findByProjetId(int projetId);
}
My question is: How can I specify in my DAO interface a method that will return all clients distinct in List<Client>?
From the documentation and JIRA:
List<Project> findAllDistinctBy();
The query builder mechanism built into Spring Data repository infrastructure is useful for building constraining queries over entities of the repository. The mechanism strips the prefixes find…By, read…By, query…By, count…By, and get…By from the method and starts parsing the rest of it. The introducing clause can contain further expressions such as a Distinct to set a distinct flag on the query to be created. However, the first By acts as delimiter to indicate the start of the actual criteria. At a very basic level you can define conditions on entity properties and concatenate them with And and Or.
You are dealing with a one-to-one relationship, in this case I guess the list that you need is not really related to specific project, you just want a distinct list of clients.
You will need to create another repository (ClientRepository) for the Client entity and add a findAllDistinct method in this repository.

Resources