Native insert JPA Spring - java

I have a many-to-many relationship between two entities:
Entity A
ID
NAME
Entity B
ID
NAME
Join Table A_B
A_ID
B_ID
I'm trying to do an insert based off of the secondary unique attributes (names). I want to avoid fetching each entity by their name and then saving (2 queries & 1 insert vs 1 insert). Effectively, I'm looking to do something like this:
#Query(nativeQuery = true, value = "INSERT INTO A_B(A_ID, B_ID) VALUES ((SELECT ID FROM A WHERE NAME = ?), (SELECT ID FROM B WHERE NAME = ?))")
void addToJoinTable(String nameA, String nameB);
I saw this post, but I'm getting exceptions because an insert doesn't return a result set. The post mentions setting nativeQuery to true would resolve the issue, but I've had no such luck... Is there another & better way to do this?
Disclaimer: I am new to JPA, so this might be a stupid question...

Related

Need help in writing a criteria query with JPA and Hibernate

Hi I am looking for JPA criteria query (Java code) for the following sql
My SQL Query:
SELECT #today := now();
select r.globalid, r.groupid from review r
left join group ug on r.globalid = ug.globalid
and r.groupid = ug.groupid --having problem here???
and #today between r.startdate and r.enddate
where ug.globalid is null
These are two entities named:
Review (ID(Primary Key),GlobalId , GroupID,.....)
Group (ID (Primary Key), GlobalId, GroupID, .....)
in the above two entities there are multiple columns.However,the two columns in both the entities are same they are, globalid and groupid
I would like to join both the tables with the matched columns using criteria query(Java JPA with Hibernate) as there is no entity relationship exists between these two entities I am confused how to join them.
Edit:
This is purely using JPA.
Any help is greatly appreciated.

JPA Join with aggregate function

I am a beginner when it comes to JPA and I am struggling to write the proper entity classes for my database structure.
Firstly, here are my tables:
create table article (
id varchar(100) not null primary key,
title varchar(255) not null
)
create table article_provider (
providerId varchar(60) not null,
articleId varchar(100) null,
isOnSale BOOL NOT NULL,
constraint article_provider_articleid_fk foreign key (articleId) references article (id) on update cascade on delete cascade
)
As you can see I have a one-to-many relationship (every article can have 0..n providers).
Now when accessing articles I would also like to know, if the article is on sale by any of it's providers. For this I would use the following SQL query:
SELECT article.*, MAX(article_provider.isOnSale) AS isOnSale FROM article
LEFT JOIN article_provider ON article.id = article_provider.articleId
GROUP BY article.id
How would I best go about fetching this type of result using Hibernate/JPA?
Your query is not right -- you use attributes in SELECT clause that are not in GROUP BY clause, but for example to select Article.id + MAX(whatever) you can use something like:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Article> query = builder.createQuery(Article.class);
Root<Article> root = query.from(Article.class);
Join<Article, ArticleProvider> join = root.join(Article_.provider, JoinType.LEFT);
query.multiselect(root.get(Article_.id), builder.max(sale));
query.groupBy(root.get(Article_.id));
// query will return collection of scalar attributes (ID + Number)
Object result = entityManager.createQuery(query).getResultList()
To select exactly Article.* + MAX(sales) you would need to use the above as a subquery and join again with Article entity.
But there are simillar of examples elsewhere: How do I write a MAX query with a where clause in JPA 2.0?
EDIT:
another tip: https://www.thoughts-on-java.org/hibernate-tip-subquery-criteriaquery/
correction/clarification: I have only assumed you want to use Criteria API where subquery and combining the results for Hibernate is probably the only way. But you may try to use JPA query language and/or different provider where subquery with multiple results can be used -- jpa eclipselink subquery in from clause

Spring Data JPA, hibernate: update all query and SET value by selecting from another table

Is the following SQL possible in a JPA query? I tried but the actual SQL hibernate runs doesn't seem right.
This is the SQL i want to write as JPA query;
UPDATE movie m SET average_rating = COALESCE((SELECT AVG(stars) FROM rating r WHERE r.movie_id = m.id), 0);
This is the JPA query;
#Query("UPDATE Movie m SET m.averageRating = COALESCE((SELECT AVG(r.stars) FROM Rating r WHERE r.movie = m), 0)")
And what hibernate says;
Hibernate:
insert
into
HT_Movie
select
movie0_.id as id
from
Movie movie0_
Hibernate:
update
Movie
set
average_rating=coalesce((select
avg(rating1_.stars)
from
Rating rating1_
where
rating1_.movie_id=id),
0)
where
(
id
) IN (
select
id
from
HT_Movie
)
so there seems to be an additional where being added by hibernate.
#Query("UPDATE Movie m SET m.averageRating = COALESCE((SELECT AVG(r.stars) FROM Rating r WHERE r.movie = m), 0)")
This is 100% correct.
And hibernate works correctly as well.
Hibernate works in this way:
Create a temporary table HT_Movie and insert the ids of Movie table.
Create the JPA query as a whole where
Compare abstracting ids from HT_Movie t enforce more speed in update processing
And this is not new hibernate always fabricates queries.

How to map native query to one model class?

Hi I´m using Eclipselink and I did a native query to select some fields of 2 tables. I mapped my table Logins in a model class. I would not like to map my table "B" because I need only 2 fields of this table on my sql result.. can I map this 2 fields in my Logins table to my sql result ?
My sql is this:
select l.login_id, s.lugarcerto,s.vrum, l.username, l.first_name, l.last_name, l.phone, l.fax_number, l.address, l.zip,
l.address2 as 'birth_date', l.city as 'cpf_cnpj'
from Logins l
join (select se.login_id, lugarcerto = min(case when se.service = 'IM' then '1' end), vrum = min(case when se.service = 'VE' then '1' end)
from (select distinct ad.login_id, substring(ap.Rate_code,(CHARINDEX('-', ap.Rate_code)+1),2) as 'service'
from Ad_Data.dbo.ad ad
join Ad_Data.dbo.ad_pub ap on (ad.ad_id = ap.ad_id)
where ap.ad_type =1) se
group by se.login_id) s on (s.login_id = l.login_id)
I did map Logins table and I want to map s.lugarcerto and s.vrum to my SQL query result.
There´s anyway to just add it to my Logins model ?
Not without having mappings for the attributes you want those values put into, and not without causing problems with them being cached in the entity.
Why not just return the values beside the entity, much like you would with a JPQL query such as: "Select l, subquery1, subquery2 from Logins l" ie:
Query q = em.createNativeQuery(yourQueryString, "resultMappingName");
And in the entity, include the annotation:
#SqlResultSetMapping(name="resultMappingName",
entities={#EntityResult(entityClass=com.acme.Logins.class, )},
columns={#ColumnResult(name="LUGARCERTO"), #ColumnResult(name="VRUM")}
)
Best Regards,
Chris

JoinColumn name not used in sql

I have a problem with mapping many-to-one relationship without exact foreign key constraint set in database. I use OpenJPA implementation with MySql database, but the problem is with generated sql scripts for insert and select statements.
I have LegalEntity table which contains RootId column (among others). I also have Address table which has LegalEntityId column which is not nullable, and which should contain values referencing LegalEntity's "RootId" column, but without any database constraint (foreign key) set.
Address entity is mapped:
#Entity
#Table(name="address")
public class Address implements Serializable {
...
#ManyToOne(fetch=FetchType.LAZY, optional=false)
#JoinColumn(referencedColumnName="RootId", name="LegalEntityId", nullable=false, insertable=true, updatable=true, table="LegalEntity")
public LegalEntity getLegalEntity() {
return this.legalEntity;
}
}
SELECT statement (when fetching LegalEntity's addresses) and INSERT statment are generated:
SELECT t0.Id, .., t0.LEGALENTITY_ID FROM address t0 WHERE t0.LEGALENTITY_ID = ? ORDER BY t0.Id DESC [params=(int) 2]
INSERT INTO address (..., LEGALENTITY_ID) VALUES (..., ?) [params=..., (int) 2]
If I omit table attribute from mentioned statements are generated:
SELECT t0.Id, ... FROM address t0 INNER JOIN legalentity t1 ON t0.LegalEntityId = t1.RootId WHERE t1.Id = ? ORDER BY t0.Id DESC [params=(int) 2]
INSERT INTO address (...) VALUES (...) [params=...]
So, LegalEntityId is not included in any of the statements.
Is it possible to have relationship based on such referencing (to column other than primary key, without foreign key in database)? Is there something else missing?
Thanks in advance.
Try changing your FetchType to eager. OpenJPA should not query for the LegalEntity until it's requested by calling getLegalEntity.
Also, the absence of constraints shouldn't matter (somebody please correct me if I'm wrong).

Categories

Resources