Hibernate creates new Tables but won't modify/add Columns - spring

Looking for next debugging steps. I'm using Hibernate with Spring Boot, with my ddl setting set to update (I realize the hibernate setting is redundant but I just wanted to be sure):
application.properties
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
hibernate.hbm2ddl.auto=update
I've just added a new Entity, which succesfully created. But when adding an additional field, profileImageURI2, nothing is ever run to attempt to add it:
#Entity
#Data
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String profileImageURI;
private String profileImageURI2;
}
Is there any additional config that will control the modification of existing tables? The user also has all permissions for the database.

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: map entity to a scheme

Im trying to create a Spring-Boot Data JPA-Application with Entities based in multiple schemes using an oracle Database.s
I have two Schemes, scheme_a and scheme_b. The DDL User for scheme_a is scheme_a, the DDL user for scheme_b is scheme_b. Both DDL user will be used by liquibase to create my initial table structure.
My application has two entities:
Entity foo is managed by my application and should be based in scheme scheme_a.
Entity bar is managed by a third party library and should be based in scheme scheme_b.
My application has a user app_user, with CRUD-rights on all tables and sequences located in scheme_a and scheme_b. This user is my DMA-user
My plan was to use Spring-Data-Jpa to connect with the database using the app-user user. This user should be able to work with all entities in scheme_a and scheme_b.
Example of Entity foo (bar has identical structure):
#Entity
#Table(name = "T_FOO")
public class FooEntity {
public FooEntity () { // no-args c-tor for hibernate
}
#Id
#Column(name = "foo_id")
#SequenceGenerator(name = "sequence_foo_id", sequenceName = "sequence_foo_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence_foo_id")
private long id;
#Column(name = "foo_name")
private String name;
}
Every entity has its own Repository:
public interface FooRepo extends CrudRepository<FooEntity, Long> {
...
}
My configuration:
#Configuration
#EnableJpaRepositories(basePackageClasses = {FooRepo.class, BARRepo.class})
#EntityScan(basePackageClasses = {FooEntity.class, BarEntity.class})
public class AppDBConfig {
...
}
But every time my application tries to start it is not able to locate the table T_FOO based in scheme_a.
I am not able to extend the #Table-Annotation with corresponding scheme. Does any one know a way to solve this problem? Is it possible to create something like a "scheme-table" to tell hibernate in which scheme which entity is located, like
var schemeMap = new HashMap<Class, String>();
schemeMap.put(FooEntity.class, scheme_a);
schemeMap.put(BarEntity.class, scheme_b);
Greetings from Germany!
You need to specify the schema in the #Table annotation.
#Entity
#Table(name = "T_FOO", schema = "scheme_a")
public static void FooEntity {
// ..
Since you don't seem to be allowed to change the annotation on FooEntity I see a couple of options available to you:
If you can change the annotation on BarEntity but not on FooEntity you can make the schema of FooEntity your default schema and set the schema for BarEntity in the annotation.
If you can't change either entity but have some control over the database you can create a view or synonym in your main schema that mirrors T_FOO.
You can also configure Hibernate with XML and specify the schema there.
You could decompile the class file containing FooEntity, add the required annotation and compile it again.
You probably could use ByteBuddy or a similar tool to do that at runtime during startup of your application.

Hibernate collection with #ElementCollection contains duplicated elements in database

Have a class.
#Entity
#Table(name="sessions")
#Component
public class Session {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ElementCollection
private Set<String> addedWords;
}
My flow is: get session one time. Add one word to addedWords and save session, repeat it. The problem that when I check my database, there are a lot of duplications, at the same time I don't have any duplications in Java class. So the Set<String> addedWords in class and this words in database not the same. Why I have this strange behavior and how to make things work well without any duplication? I use PostgreSQL. Saving method:
public synchronized void addWord(Session session, String word) {
session.getAddedWords().add(word);
sessionRepository.save(session);
}
Here spring config
spring:
jpa:
show-sql: true
hibernate:
ddl-auto: update

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

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.

Resources