HQL query for Association - hql

I am having below tables here but having some problem while fetching results.
#Entity
#Table(name = "USER_VW")
public class WorkspaceUserImpl
{
#JoinColumn(name = "USER_ID", insertable=false, updatable=false)
#OneToOne(targetEntity = UserImpl.class, fetch = FetchType.EAGER)
private User user;
}
#Table(name = "IK_USER")
#Inheritance(strategy = InheritanceType.JOINED)
#AttributeOverride(name = "id", column = #Column(name = "USER_ID") )
public class UserImpl extends BaseAuditable<UserIdentifier>implements User, UserAuthentication {
private static Logger log = LoggerFactory.getLogger(UserImpl.class);
#Id
#Type(type = "com.commons.UserIdentifierTypeMapper")
#Column(name = "USER_ID")
private UserIdentifier id;
}
and User
Public Inteface User
{
UserIdentifier getId();
}
Now i have written an HQL query to fetch all the data from WorkspaceUserImpl class with a given user ID for UserImpl class like below.
SELECT w from WorkspaceUserImpl w where w.user.id = : user_id;
and also tried
SELECT w from WorkspaceUserImpl as w INNER JOIN w.user as u where u.id = : user_id;
and even tried with JOIN FETCH also
and setting the parameter user_id with some say 1234.
but am getting List as emply for the partcular ID but in DB its having 5 records.
am i making any query mistake here? kindly advice..

Have you tried below query:
from WorkspaceUserImpl as w JOIN FETCH w.user as u where u.id = : user_id;

Related

JPA Native Query. Cannot select specific columns

I'm working on a Spring Boot project using JPA to connect to my DB. I wan to make a native query to select some specific fields but it doesn't allow me to do. For example, I want to get only id, firstName, lastName and phoneNumber of a customer But it will throws me error like,
The column name current_access_token was not found in this ResultSet.
Here is my query code in the JPA repository,
#Query(value = "SELECT c.id, c.phone_number, c.firstname, c.lastname FROM tbl_customers c JOIN tbl_subscriptions s ON c.id = s.customer_id WHERE s.role = 'member' AND s.deleted_at IS NULL", nativeQuery = true)
List<Customer> findMemberByRole(String role);
Here is my Cutomer.java
#Getter
#Setter
#Accessors(chain=true)
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "tbl_customers")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique = true)
private Long id;
#Column(nullable = false, name = "phone_number")
private String phoneNumber;
private String firstname;
private String lastname;
#Column(name = "current_access_token")
private String currentAccessToken;
#Column(name = "consent_accepted")
private Boolean consentAccepted;
...
...
}
How can I avoid or ignore unwanted columns? Thanks a lot for helps.
If you really want to return only 4 columns from the customer table, then the signature you want to use here is List<Object[]>:
#Query(value = "SELECT c.id, c.phone_number, c.firstname, c.lastname FROM tbl_customers c JOIN tbl_subscriptions s ON c.id = s.customer_id WHERE s.role = 'member' AND s.deleted_at IS NULL", nativeQuery = true)
List<Object[]> findMemberByRole(String role);
Then, when accessing your result set, you would use something like:
List<Object[]> resultSet = findMemberByRole("admin");
for (Object[] rs : resultSet) {
Long id = (Long) rs[0];
String phoneNumber = (String) rs[1];
String firstName = (String) rs[2];
String lastName = (String) rs[3];
}

Spring boot JPA - Insert or update a list of entities

I have a repo with a unique constraint on 2 fields, connection_id and token_type:
#Entity
#Table(
name = "business_api_token",
schema = "public",
uniqueConstraints = {
#UniqueConstraint(
name = "business_api_token_unique_connection_id_and_token_type",
columnNames = {"connection_id", "token_type"}
)
}
)
public class BusinessApiToken {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToOne
#JoinColumn(
name = "connection_id",
nullable = false,
foreignKey = #ForeignKey(
name = "fk_business_api_token_connection_id"
)
)
private AccountingConnection connection;
#Column(name = "token_type")
#Enumerated(EnumType.STRING)
private ApiTokenType tokenType;
#Column(name = "token_value")
private String tokenValue;
...
}
I saw some posts saying add a custom query, something like this:
#Modifying
#Query("update User u set u.firstname = ?1, u.lastname = ?2 where u.id = ?3")
void setUserInfoById(String firstname, String lastname, Integer userId);
But how would I do this for a list? I was doing this:
businessApiTokenRepository.saveAll(tokens)
Which gives an error.
The tokens are created elsewhere without knowledge of existing ones, I can do another query to check first but that seems inefficient, and I have to do this all over.
Thanks

Delete Operation on Embedded Object Spring JPA

I Have below Entities :
#Entity(name = "USRGRP_MAP")
public class UserGroupMapping {
#Id
#Column(name = "USRGRP_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_GRP_MAP_SEQ")
#SequenceGenerator(sequenceName = "usrgrp_map_seq",allocationSize = 1,name = "USER_GRP_MAP_SEQ")
private Long mappingId;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "USER_ID", referencedColumnName = "USER_ID")
private User user;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "USR_GRP_ID", referencedColumnName = "USR_GRP_ID")
private UserGroup group;
#Column(name = "USR_USRGRP_ACT")
private String userGroupAct;
getter/setters
}
#Entity(name = "USER")
public class User {
#Id
#Column(name = "USER_ID")
private Long userId;
#Column(name = "LOGIN_ID")
private String userName;
getter/setters
}
#Entity(name = "USR_GRP")
public class UserGroup {
#Id
#Column(name = "USR_GRP_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_GRP_SEQ")
#SequenceGenerator(sequenceName = "usr_grp_seq",allocationSize = 1,name = "USER_GRP_SEQ")
private long groupId;
#Column(name = "GRP_NM")
private String groupName;
#Column(name = "GRP_DESC")
private String groupDesc;
getter/setters
}
UserGroupMapping contains has many to one relationship with both user and group.
Now I want to do CRUD operation on UserGroupMapping for that I have created repository as below:
public interface UserGroupMappingRepository extends JpaRepository<UserGroupMapping, Long> {
List<UserGroupMapping> findByGroup(UserGroup group);
List<UserGroupMapping> findByUser(User user);
}
Now I want to write delete operation(for particular user and group) on UserGroupMapping without deleting any entry in USER and USR_GRP table , Just need to remove entry from USRGRP_MAP table.
I am trying to achieve it using native query:
#Query(value = "delete from USR_USRGRP_MAP where user_id = :userId and usr_grp_id = :groupId",nativeQuery = true)
void deleteUserGroupMappingByUserAndGroup(#Param("userId") Long userId, #Param("groupId") Long groupId);
Facing Exception Invalid SQL grammar, although query work fine in sql developer.
Below is my service class:
#Service
public class UserGroupMappingServiceImpl implements UserGroupMappingService{
#Autowired
private UserGroupMappingRepository repository;
#Override
public void deleteUserGroupMapping(Long userId, Long groupId) {
repository.deleteUserGroupMappingByUserAndGroup(userId,groupId);
}
}
Could anyone suggest correct way to delete entry from UserGroupMapping without deleting user and group ?
Below is USRGRP_MAP table:
USRGRP_ID USER_ID USR_USRGRP_ID USR_USRGRP_ACT
------------- ---------- ------------- -
41 306106 41 Y
14 108527 14 Y
8 295597 8 N
10 296518 10 Y
11 295597 11 Y
Thanks in advance .
Try to change
#Query(value = "delete from USR_USRGRP_MAP where user_id = :userId and usr_grp_id = :groupId",nativeQuery = true)
void deleteUserGroupMappingByUserAndGroup(#Param("userId") Long userId, #Param("groupId") Long groupId);
To this:
#Modifying
#Query(value = "delete from USR_USRGRP_MAP where user_id = :userId and usr_grp_id = :groupId",nativeQuery = true)
void deleteUserGroupMappingByUserAndGroup(#Param("userId") Long userId, #Param("groupId") Long groupId);
Cheers
~Emil

Spring boot JPA filter by join table

I cant find something concrete in the docs (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation)
and no satisfying answere in several blogs.
so here my question.
I have table Entity like:
#Entity
#Table(name = "workstation")
public class Workstation
{
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "userid", nullable = false)
public User user;
}
And the user table Entity:
public class user
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
public Integer id;
#Column(name = "age", nullable = false)
public int age
}
Now I would like to have a query in my Repository like this:
public interface WorkstationRepo extends CrudRepository<Workstation, Long> {
findByUserAgeLesserThan(int maxAge);
}
Means I want to find all user who are under a certain age through my Workstation Entity.
And is it possible without a #Query annotation? Or/And how should it look like?
Try this
List<Workstation> findByUserAgeLessThan(int maxAge);
Alternatively you can also write your query
#Query("Select w from Workstation w where w.user.age < :maxAge")
List<Workstation> findByUserAgeLesserThan(#Param("maxAge") int maxAge);
This works:
#Query("SELECT w from Workstation w INNER JOIN w.user u where u.age < ?1")
List<Workstation> findByUserAgeLessThan(int age);
You should have something like this:
#Query("SELECT w from Workstation w INNER JOIN w.user u where u.age < :age")
List<Workstation> findByUserAgeLessThan(#Param("age") int age);
Basically, you need to JOIN the tables using JPQL.

Inner join in spring boot data jpa

I am using spring boot data jpa 1.4 and I'm fairly new to it.
My table definition is here. Its fairly simple, there are 2 tables (Groups and Users).
The group table contains group_id(primary key), group_name, group_active(values=Y/N).
The group table can ideally have only one row which is has group_active to 'Y', the rest should have 'N'
The user table contains user_id(primary key), user_name, group_id(foreign key from group).
Following are my entity classes
Group:
#Entity
#Table(schema = "HR", name = "GROUPS")
public class Group {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "GROUP_ID")
private Long id;
#Column(name = "GROUP_NAME")
private String name;
#Column(name = "GROUP_ACTIVE")
private String active;
User:
#Entity
#Table(schema = "HR", name = "USERS")
public class User {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "USER_ID")
private Long id;
#Column(name = "USER_NAME")
private String name;
#Column(name = "GROUP_ID")
private Long groupId;
#ManyToMany
#JoinTable(
schema = "HR",
name = "GROUPS",
joinColumns = {#JoinColumn(table = "GROUPS", name = "GROUP_ID", insertable = false, updatable = false)},
inverseJoinColumns = {#JoinColumn(table = "USERS", name = "GROUP_ID", insertable = false, updatable = false)}
)
#WhereJoinTable(clause = "GROUP_ACTIVE='Y'")
private List<Group> group;
Repository class:
public interface UserRepository extends CrudRepository<User, Long>{
List<User> findByName (String name);
}
Query: This is the query I want to execute, which is a simple inner join.
SELECT U.*
FROM HR.USER U, HR.GROUP G
WHERE U.GROUP_ID=G.GROUP_ID
AND G.GROUP_ACTIVE='Y'
AND U.USER_NAME=?
What would be the correct way to write the #JoinTable or #JoinColumn such that I always get back one user that belongs to the active group with the name ?
I have done some tests based on your set-up and the solution would need to use filters (assuming there is only one Group with Group_Activity = 'Y'):
Group Entity
#Entity
#Table(schema = "HR", name = "GROUPS")
public class Group {
#OneToMany(mappedBy = "group")
#Filter(name = "activityFilter")
private Set<User> users;
User Entity
#Entity
#Table(schema = "HR", name = "USERS")
#FilterDef(name="activityFilter"
, defaultCondition="group_id =
(select g.id from groups g where g.GROUP_ACTIVE='Y')")
public class User {
#ManyToOne
#JoinColumn(name = "group_id")
private Group group;
When making a query
session.enableFilter("activityFilter");
session.createQuery("select u from Group g inner join g.users u where u.user_name = :userName");
Additionally if there are many groups with activity = 'Y' then try this:
#FilterDef(name="activityFilter"
, defaultCondition="group_id in
(select g.id from group g where g.GROUP_ACTIVE='Y')")

Resources