#Query with or, and - mysql

In my db I have two types of users: test and production. I have the method to search them by id or order number. In db is column with boolean param isTest (true if user is from test enviroment and false for other). I have to make query in repository(spring data, jpa) with free params (id, oorderId and isTest) and I want to display only productions users. I made something lkie this (but doesn't work, I mean the search by orderId or id is ok but boolean property is not):
public interface UserRepository extends JpaRepository<User, Long>{
#Query(select u from User where u.orderId = ?1 or u.id = ?1 and isTest = false")
Page<User> searchUsers(Pageable pageable, String orderId, String id, boolean isTest);
}
Thanks for help

As documented under Operator Precedence, AND has higher precedence than OR. Therefore your current filter is evaluated as:
WHERE u.orderId = ?1 OR (u.id = ?1 AND isTest = false)
You should add explicit parentheses to force the precedence that suits your requirements:
WHERE (u.orderId = ?1 OR u.id = ?1) AND isTest = false

Related

spring jpa join and query repository

I have User class like this:
{
...
Long userID;
...
List<UserMovieRole> userMovieRoles=...
}
A Movie class like this:
{
...
Long movieID;
...
List<UserMovieRole> userMovieRoles=...
}
I have another class UserMovieRole like this:
{
Long userMovieRoleID;
Role role;
...
User user;
...
Movie movie;
}
Now I want to query on UserMovieRole and select where userID and movieID is given.
In sql I can simply write, I can simply write a join and where sql to select.
But in spring boot jpa query, it seems I can't do that, how can I do that?
Here is what I have tried:
#Query("select umr from UserMovieRole umr where umr.user.userID=?1 and umr.movie.movieID=?2")
#Query("select umrj from UserMovieRole.user full join UserMovieRole.movie umrj where umrj.userID=?1 and umrj.movieID=?2")
I dont't know if any of these are correct, what is the actual way of doing it ?
Write a query as you would in SQL in the #Query and then add another property of the annotation as nativeQuery = true and it will run the query as you would in sql.
Pass the parameters in query by adding a : in front of them. Also, don't forget to add #Param in your auguments.
Something like this:
#Query(value = "select umr from UserMovieRole umr join user u on u.id = umr.userId where u.userId (#got it by joining tables.) = :userId and umr.movieID=:movieId", nativeQuery = true)
returnType yourMethod(#Param("userId") userId, #Param("movieId") movieId);

Select record where id is one of collection id

In a spring mvc application i have 3 database tables (including one mapping table) and their 2 corresponding java entities.
The entities are:-
public class User {
private Long id;
private String userName;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "user_location",
joinColumns = {#JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "location_id", referencedColumnName = "id")}
)
private Set<Location> location;
}
public class Location {
private Long id;
private String locationCode;
}
Three tables are users, location and user_location.
I want to select a user whose location id is equal to a particular id.
Since user can have multiple locations i am not sure how to write a hibernate query for this. I tried few combinations below but i am either getting a exception,
illegal attempt to dereference collection [{synthetic-alias}{non-qualified-property-ref}] with element property reference [id]
or getting a list of User and Location objects. i just want a list of user objects.
from User where userName = :userName and :locationId in (location.id)
from User user inner join user.location loc where user.userName = :usersName and loc.id = :locationId
Update:
I tried query,
Query query = getCurrentSession().createQuery("from User user inner join user.location loc where user.userName = :usersName and loc.id = :locationId");
Hibernate generates following plain SQL from above query and returns a list of User and Location objects. For example if there is one location for an user that matches above query hibernate returns a list that contains one User and one Location object.
select
user0_.id as id1_18_0_,
location2_.id as id1_5_1_,
user0_.user_name as user_na11_18_0_,
location2_.location_code as location3_5_1_
from
users user0_
inner join
user_location location1_
on user0_.id=location1_.user_id
inner join
location location2_
on location1_.location_id=location2_.id
where
user0_.user_name=?
and location2_.id=?
You could try to use next criteria:
Criteria criteria = getCurrentSession().createCriteria(User.class, "u");
criteria.createAlias("location", "loc");
criteria.add(Restrictions.eq("u.userName", "userName");
criteria.add(Restrictions.eq("loc.id", locationId);
List<User> users = criteria.list();
Or you could try HQL typed query:
TypedQuery<User> query =
getCurrentSession().createQuery("SELECT User.* FROM User u JOIN user_location ul ON u.id = ul.user_id JOIN Location l ON ul.location_id = l.id WHERE u.userName = :userName AND l.id = :locationId", User.class)
.setParameter("userName", "userName")
.setParameter("locationOd", locationId);
List<User> users = query.getResultList();

hibernate optional relationship not showing data

I am using hibernate with MySQL Db. I have a table of business with some fields and relations. in relations, one relation is optional.
#ManyToOne(fetch = FetchType.LAZY)
#NotFound(action=NotFoundAction.IGNORE)
#JoinColumn(name = "modified_by", nullable = true)
public Users getModifiedBy() {
return this.modifiedBy;
}
public void setModifiedBy(Users modifiedBy) {
this.modifiedBy = modifiedBy;
}
now when I fetch data using the following hql it work fine
String hql = "from Business";
Query query = session.createQuery(hql);
list = query.list();
if i changed hql to the following then it shows 0 result.
String hql = "select new com.ba.Business(business.businessId,business.slUsersByCreatedBy.userId,business.modifiedBy.userId,business.bizType.bizTypeId) from com.ba.Business business order by business.businessName";
How to manage this as modifiedBy is null. There were different solution available which i tried like setting optional to true and setting #NotFound but nothing worked.
SQL Created by hql is following.
select business0_.business_id as col_0_0_, business0_.createdBy as col_1_0_, business0_.modified_by as col_5_0_, business0_.biz_type_id as col_9_0_ from _business business0_, _users users1_, _users users4_, _biz_type biztype7_ where business0_.createdBy= users1_.web_user_id and business0_.modified_by= users4_.web_user_id and business0_.biz_type_id= biztype7_.biz_type_id order by business0_.business_name
it is using "and" for joins. If i explicitly add joins by adding following with hql then the result remain same.
left join business.modifiedBy modifiedBy
Is there any solution available?
When you use business.modifiedBy in the query, it implicitly converts to inner join, and that's why you don't get any results. Change it to this and it should work
String hql = "select new com.ba.Business(business.businessId, business.slUsersByCreatedBy.userId, mb.userId, business.bizType.bizTypeId) from com.ba.Business business left join business.modifiedBy mb order by business.businessName";

How Do I use Having and group By clause in hibernate?

I have a sql Query which is something like this.
SELECT VERSION_ID FROM VIEWTEST
where ( item_id='I001' and value ='V001')
or ( item_id='I002' and value ='V002')
or ( item_id= 'I003'and value ='V003')
group by VERSION_ID
having count(1) = 3
My ViewTest entity is something like this.
#Column(name = "version_id")
private String versionId;
#Column(name = "item_id")
private String itemId;
#Column(name = "value")
private String value;
Here is the Crieteria Query written by me.
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<String> query = criteriaBuilder.createQuery(String.class);
Root<ViewTest> testRoot = query.from(ViewTest.class);
List<Predicate> predicates = new ArrayList<Predicate>();
Predicate p1 = criteriaBuilder.equal(testRoot.get("itemId"), "I001");
Predicate p2 = criteriaBuilder.equal(testRoot.get("itemId"), "I002");
Predicate p3 = criteriaBuilder.equal(testRoot.get("itemId"), "I003");
Predicate v1 = criteriaBuilder.equal(testRoot.get("value"), "V001");
Predicate v2 = criteriaBuilder.equal(testRoot.get("value"), "V002");
Predicate v3 = criteriaBuilder.equal(testRoot.get("value"), "V003");
predicates.add(criteriaBuilder.and(p1 , v1));
predicates.add(criteriaBuilder.and(p2 , v2));
predicates.add(criteriaBuilder.and(p3 , v3));
Now I dont know how to add group By and Having clause to this criteria.
Can someone please help me out?
Found a better way to do it.
just added below to my code.
query.groupBy(testRoot.<String> get("versionId"));
query.having(criteriaBuilder.in(criteriaBuilder.count(testRoot.get("versionId"))).value(
queryCount));
this did the trick.
Have you looked at Projections?
Hibernate developer guide: Projections
Example:
List results = session.createCriteria(Cat.class)
.setProjection( Projections.projectionList()
.add( Projections.rowCount() )
.add( Projections.avg("weight") )
.add( Projections.max("weight") )
.add( Projections.groupProperty("color") )
)
.list();

Not returning all the required rows using MySQL

so here is my issue:
i have 3 tables:
ROLE : RID ,NAME
CLIENT : CID, NAME
USER : UID, RID, CID, USERNAME, PASSWORD
Below is the SQL statement that I have written:
SELECT USER.UID,USERNAME,PASSWORD,ROLE.NAME, ROLE.RID
FROM USER
INNER JOIN ROLE ON USER.RID=ROLE.RID
WHERE CID=1;
The above statement is returning only 1 row when there should actually be 2 rows.
I don't understand what is not working.
When i do the following, i get my 2 rows:
SELECT *
FROM USER
WHERE CID =1;
Note that i am using spring framework and also implementing a RowMapper. Below is my actual code with the field names as per the dbase.
public List<User> viewUserClient(int client_id) {
String sql =
"SELECT USER.ID,USERNAME,PASSWORD,ACTIVE,ROLE.NAME, ROLE.ID FROM USER INNER JOIN ROLE ON USER.ROLE_ID=ROLE.ID WHERE CLIENT_ID=?";
List<User> users = this.getJdbcTemplate().query(sql, new Object[] { client_id }, new UserClientRowMapper());
return users;
}
private static final class UserClientRowMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
Client client = new Client();
Role role = new Role();
user.setID(rs.getInt("ID"));
user.setUSERNAME(rs.getString("USERNAME"));
user.setPASSWORD(rs.getString("PASSWORD"));
user.setACTIVE(rs.getBoolean("ACTIVE"));
role.setNAME(rs.getString("NAME"));
role.setID(rs.getInt("ROLE.ID"));
client.setId(rs.getInt("id"));
client.setName(rs.getString("name"));
user.setRole(role);
user.setClient(client);
return user;
}
}
Thanks in advance for your help.
The INNER JOIN keyword returns rows when there is at least one match in both tables. If there are rows in "USER" that do not have matches in "ROLE", those rows will NOT be listed; of the two users returned by your plain select query, probably one has a null RID column value, or a value that is not in ROLE table.
Use a LEFT JOIN.