Springboot Joint table from different database - spring-boot

I have a Springboot project with two datasource configured one for each database I'm using. Everything works, but I need to create an Entity in database one that refers to an entity from database 2. The problem is that the entity in the second database is not found.
#Entity
#Table(name = "data", catalog = "data")
public class Data implements Serializable
{
//all stuff related to data here.
#ManyToOne
private User user;
//Entity User is store in the second database
}
Is there anyway to tell spring that the entity User can be found in the second datasource?

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.

Multiple Repositories for the Same Entity in Spring Data Rest

Is it possible to publish two different repositories for the same JPA entity with Spring Data Rest?
I gave the two repositories different paths and rel-names, but only one of the two is available as REST endpoint.
The point why I'm having two repositories is, that one of them is an excerpt, showing only the basic fields of an entity.
The terrible part is not only that you can only have 1 spring data rest repository (#RepositoryRestResource) per Entity but also that if you have a regular JPA #Repository (like CrudRepository or PagingAndSorting) it will also interact with the spring data rest one (as the key in the map is the Entity itself).
Lost quite a few hours debugging random load of one or the other. I guess that if this is a hard limitation of spring data rest at least an Exception could be thrown if the key of the map is already there when trying to override the value.
The answer seems to be: There is only one repository possible per entity.
I ended up using the #Subselect to create a second immutable entity and bound that to the second JpaRepsotory and setting it to #RestResource(exported = false), that also encourages a separation of concerns.
Employee Example
#Entity
#Table(name = "employee")
public class Employee {
#Id
Long id
String name
...
}
#RestResource
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {
}
#Entity
#Immutable
#Subselect(value = 'select id, name, salary from employee')
public class VEmployeeSummary {
#Id
Long id
...
}
#RestResource(exported = false)
public interface VEmployeeRepository extends JpaRepository<VEmployeeSummary, Long> {
}
Context
Two packages in the monolithic application had different requirements. One needed to expose the entities for the UI in a PagingAndSortingRepository including CRUD functions. The other was for an aggregating backend report component without paging but with sorting.
I know I could have filtered the results from the PagingAndSorting Repository after requesting Pageable.unpaged() but I just wanted a Basic JPA repository which returned List for some filters.
So, this does not directly answer the question, but may help solve the underlying issue.
You can only have one repository per entity... however, you can have multiple entities per table; thus, having multiple repositories per table.
In a bit of code I wrote, I had to create two entities... one with an auto-generated id and another with a preset id, but both pointing to the same table:
#Entity
#Table("line_item")
public class LineItemWithAutoId {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
...
}
#Entity
#Table("line_item")
public class LineItemWithPredefinedId {
#Id
private String id;
...
}
Then, I had a repository for each:
public interface LineItemWithoutId extends Repository<LineItemWithAutoId,String> {
...
}
public interface LineItemWithId extends Repository<LineItemWithPredefinedId,String> {
...
}
For the posted issue, you could have two entities. One would be the full entity, with getters and setters for everything. The other, would be the entity, where there are setters for everything, but only getters for the fields you want to make public. Does this make sense?

Could not execute JDBC batch update

I have a problem with a entity class. When I run my app with hibernate.hbm2ddl.auto = create, then it create all the other entity tables but not this on. Why is that? And when I create the table by myself and after that try to insert something into it, then I get this error: http://pastebin.com/m4gjxqNC
Here's my entity class:
User entity:
http://pastebin.com/YXvzFSgt
Comment entity:
http://pastebin.com/RpZEUPxN
And here's the UserDAO class
http://pastebin.com/LrTCg0GC
You seems to be using PostgreSQL. As per this document, 'User' is a PostgreSQL reserved word. Try adding a #Table("user_tb") annotation for your User entity, to force a new table name.
#Entity
#Table("user_tb")
public class User extends LightEntity implements Serializable {
//..
}

Resources