In Spring Data JPA using Schema Multi Tenant, how to join with other schema although the same entity - spring

I am using schema-based multitenancy in Spring Data JPA.
properties.put("hibernate.multiTenancy", MultiTenancyStrategy.SCHEMA);
The table structure of the "Common" schema and the "A" schema is the same.
These two schemas are multi-tenant structures that use the same entity.
There's an entry called User in "A" schema and "Common" schema.
How do I join these two entities?
I want to create a query like this. (The schema is currently selected as A by Tenant setting.)
select u.* from user u left join common.user u2 on u.common_id = u2.id;
#Entity
public class Entity {
#Id
private Long id;
private Long commonId; // right?
}
Should I use native query without using JPQL?

That's not possible with JPA.
Btw. JPA doesn't know multitenancy that's a Hibernate feature.

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.

Is there a way to fetch a class with associated classes in a single SELECT query in Spring Data JPA?

I have two classes, A and B with a One-To-Many relationship.
#Entity
public class A {
//some code
#OneToMany(fetch = FetchType.LAZY, mappedBy = "abc")
private List<B> b;
}
I have a JPA Repository for A, and I observed that when I fetch an A from the database with a repository method, Bs are not included. When I want to access Bs, additional SELECT queries are executed to fetch associated Bs(if there are 100 associated Bs, 100 additional queries are executed). making FetchType.EAGER only changes when these additional SELECT queries are executed. i.e. they are called right after the main SELECT query. Either way, additional SELECT queries are executed to fetch associated classes.
Is this natural behavior? I found that JPA Entity Graphs is the solution for this issue/to fetch A with Bs with a single SELECT query. Are there any other ways to address this issue? The problem with #EntityGraph is it has to be annotated with each repository method separately. Also, is there a way to annotate #EntityGraph once so it affects all the methods in the Repository?
I'm using Spring Boot 2.5.1. Thanks in advance!

Is it necessary to use Entity annotation for Select query records from Database

I have spring boot application with JPA and MySQL. The table is already created and data are present. From the spring boot application, we need to create two API - get a particular record using id and get all the records. I created a model class but confused with usage of #Entity. Because I'm not going to insert/delete a record from the database. I want to use only for select the record.
For Select query (findBy), do we need to use #Entity annotation at the top of model class?
Yes, you would need to use #Entity to mark your model class, this tells JPA that your class is used for mapping to and from a database table. If you want to make sure that you don't accidentally overwrite the data, you could implement a check via #EntityListener, as described in this answer.

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)

join more than one table in spring jparepository

I am trying to fetch record by doing a join. I am new to spring jparepository.
I understand that there is separate repository for each entity(table) where when i implement i need to define the entity and datatype of primary key.
Could anyone please suggest how can I fetch record by joining two tables.
I have two repo as below:
public interface AEntityRepository extends JpaRepository<AEntity, Integer>
public interface BEntityRepository extends JpaRepository<BEntity, Integer>
I want to join above two entity(AEntity, BEntity).
I know I can have custom query using something like below:
#Query("SELECT ****** FROM AEntity ae")
AEntity findCustomrRecords();
However can I write the same kind of query (join query) with join.
Do i need to have a separate repository implementing some other class.
Can anyone please help.
I am using mysql.
I understand that there is separate repository for each entity(table)
This is a very common misunderstanding. You do not want to have a repository per entity, but per aggregate root. See http://static.olivergierke.de/lectures/ddd-and-spring/
Regarding your specific problem at hand: Creating a custom method in your repository interface and annotating it with a JPQL should do the trick. So you get something like:
#Query("select a from BEntity b join b.a a where b.foo = :foo")
AEntity getAllFooishAs(String foo);
You can use any join syntax JPQL offers in the query.

Resources