JPA get parent from child - java

I have two tables Companies and Users, where each company has many users, and I want to do a query on the users table where the column IS_VERIFED equals false. In my User entitie I set the XMLTransient property on the getCompany method to avoid an infinite loop of the user getting the company and the company getting the user.
I preform my query to get all the users that are not verifed, which return a List<User>. But I also want to return the company that each User belong to.
I can loop through the users array like this
List<User> users = entityManager.createNamedQuery("User.getPendingUsers").getResultList();
for (User user : users) {
logger.debug(user.getCompany().getCompanyId() + "");
logger.debug(user.getCompany().getCompanyName() + "");
}
And I see the company ID and name printed out, but now I want to return that list of users with the companies referenced how can I do this?
Thanks

Related

How to check if a node belongs to another node in a tree

I have a tree of users and I need to check if an user is below another specific user.
In example: check if user7 is below user1 somewhere in the tree so user1 can see and manage the data of user7 (see the image I've attached).In this case it should be true What will be the best/ a good approach to do this?
Edit: I don't think just traveling the tree until it find the ancestor will work because if the users are in a database it will need multiple relational queries and won't be scalable
Edit: What I trying to achieve is an app where an user can manage the users that the user registers and those that the latter registers as well, and so on. Like in the image, user admin can manage all, user 1 can manage user 3,4 and 5 and all below them too. User4 can manage user6. User 1 can't manage user 2 neither user3 to user7
Edit: one approach I have figured is to create in a SQL database a user_administrators property in the users database table that have an array of user_id who can manage it and when they register an user just inherit all the users_id and add itself to it. But I don't know if there's a better way to do it or a more scalable way
As you mention a dependency on a database, here is an example of what you could do on an SQL database that supports recursive queries, such as MySQL 8+:
Creation of the schema:
create table user (
id int auto_increment primary key,
name varchar(100),
manager_id int null
);
create index idx_user_name on user(name);
Populate with the example data given in the question:
insert into user(name) values("User Admin");
insert into user(name, manager_id)
select name, (select id from user where name = "User Admin")
from (select "User 1" name union select "User 2") names;
insert into user(name, manager_id)
select name, (select id from user where name = "User 1")
from (select "User 3" name union select "User 4" union select "User 5") names;
insert into user(name, manager_id)
select "User 6", (select id from user where name = "User 2");
insert into user(name, manager_id)
select "User 7", (select id from user where name = "User 4");
Now to know whether User 1 is in the manager line of User 7, perform this query:
with recursive cte as (
select id, name, manager_id
from user where name = "User 7"
union all
select user.id, user.name, user.manager_id
from cte inner join user on cte.manager_id = user.id
)
select 1 from cte where name = "User 1";
This query first locates the record for "User 7" and then walks up the tree collecting all persons on the manager line. Finally a simple select checks whether "User 1" occurs in this line.
If this query has a result record (the 1 is irrelevant), then the answer is "Yes". If the query returns no record, the answer is no.
If you can use the id fields instead of the name fields to identify users, that would be preferable as names could be non-unique.
Ensure that for every node you can either navigate top-down or bottom up.
If top down, have a function that assembles the list of subnodes recursively,
Once you have that, simply ask whether the node in question is amongst the subnodes of the reference node, or
If bottom-up, have a function that assembles the list of ancestors. Once you have that, simply ask wether the node in question is amongst the ancestors of the node in question.
Very likely the bottom-up approach is faster, regardless whether you have deep or wide trees.

How to store results into a Map in hibernate?

I need one help.
I have a table - ACCOUNT which stores USER_ID and ACCOUNT_DETAIL. There are multiple records for a single USER_ID with different ACCOUNT_DETAIL.
I want to store this records in a Map where USER_ID will be the key and List of Account will be the value. I get the list of USER_ID
from USER table. Then for each of those user id I need to get account details.
I can populate that map by implementing below algorithm\logic :
Step 1 : Fetch userIds from USER table and store it in a list - userList
Step 2:
for (User user : userList) {
// Make a DB call to ACCOUNT table for user.id
// Put those details in the map - map.put(user.id, accountList)
}
But here the issue is, if USER table is having 1K records I have to make 1K db calls from that loop which will end up with a performance issue.
Could you please tell me if there is any better approach through which I can achieve this using hibernate ?
Use the HQL join query(ACCOUNT and USER) to get all the accounts and construct the map by iterating the accounts.
select acc from Account acc, User usr where acc.userId = usr.id

Logging into specific account, retrieving account data

I'm trying to build an application which uses a database, that allows user to log in as an admin or employee.
Admin has few options:
add new employee,
list all employees and
add TODO Items for selected employee
Employee
display TODO items when logged in.
The first problem I've encountered is:
Should I create just one table for all records(employees & admins) and specify their name, username, password, status (admin or employee) or create separate tables for login credentials(username, password) and user data(like name, last name etc) to keep it separated?
Second problem is
I can't figure out how to display list of items for a user that has successfully logged in. How to access the data of the user that is logged in?
The first problem I've encountered is:
Should I
1=> create just one table for all records(employees & admins) and specify their name, username, password, status (admin or employee) or
2=> create separate tables for login credentials(username, password) and user data(like name, last name etc) to keep it separated?
Its better to make all user data in one data-set (Table)
No need to separate login credentials in a separate table in your case.
Second problem is I can't figure out how to display list of items for
a user that has successfully logged in.
How to access the data of the user that is logged in?
Something like that
Each Item in ITEM table should has a field called say USER_ID
And ONLY managers can update and set this field value
Then your query will be
SELECT *
FROM ITEM
WHERE USER_ID = 'logged_user_id'
One approach will be to
Create a profile or user table for thr user (employee or admin) and have userid(primary key), userloginname,userfirstname,userlastname,password(encrypted),email,role(ADMIN for admin or EMPLOYEE for employees),hintquestion etc.,.
2.Then create a table for todo tasks with columns like taskid,taskname,taskdescription etc., along with userid column(foriegn key) which will link this table to the primary key of profile table. (This answers your question on how to validate and fetch employee record).After login store user or profile object in session for the duration of the session).
3.When the user logs in validate the credentials against the username(the one user uses for login) and password stored in the profile table and fetch that record.
4.When adding employer, add the user to the profile table.
5.When adding todo tasks, add the todo items in the todo table using the userid fetched from the profile table.
6.When listing the todo items, fetch the record for thr logged in user and using the userid, fetch the todo items for the userid. (This answers your question on how to fetch the todo items)
7.When deleting the employee, delete the record from profile table and using the userid delete thr todo items from the todo items table.
Hope this helps.

Delete using NOT IN clause in HQL

I have a table issue_assigned having user_id as Integer and issue number as Varchar. The issues can be assigned to multiple users.
Now there is a condition if the issue is previously assigned to 3 users and then admin wants to assign it only to 2 users, The system should delete the 3rd user entry for that I wrote following code
String hql = "delete from issueAssigned where issueNumber=:issueNum AND assignedToUserId not in (:userIds)";
Query query = getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql);
query.setParameter("issueNum", issueNum);
query.setParameter("userIds", userIds);
if(query.executeUpdate() > 0){
return "success";
}else{
return "error";
}
userIds is a string which contain userId seperated by comma(,). When executed I get String cannot be caste to integer error.
How can i keep the required users and delete rest? What changes I will have to do?
userIds is a string which contain userId seperated by comma(,)
It shouldn't be. You should just pass an array or collection of user IDs. Hibernate will create the corresponding SQL prepared statement for you, by adding a parameter placeholder for each user ID.
And the parentheses around :userIds aren't needed either.
Instead of setParameter which take only one parameter you have to use setParameterList which take a Collection of parameters not String :
query.setParameterList("userIds", userIds);
Your query will be
String hql = "delete from issue_assigned where issue_number=:issueNum AND assigned_to_user_id not in :userIds";
and use query.setParameterList as follows
query.setParameterList("userIds", userIds);
hibernate will create the prepared statement using the collection passed.

Does select return last inserted row while autocommit set false?

Say I have a table named users and a column named username with the format user1, user2 ..
I want to insert users into this table in a loop and value of every entry depends on the one's before. Value of the new entry is generated by the alphabetically greatest entry in the table, namely users.
Since it's possible in JDBC API to getGeneratedKeys after an insert while AutoCommit set to false;
In a situation like given below:
connection.setAutoCommit(false);
while(someCondition)
{
ResultSet rs = connection.createStatement("select max(username) from users").executeQuery();
if(rs.next())
{
name= rs.getString("username"); //returns user1
}
String newName = generateNewName(name); // simply makes user1 -> user2
connection.createStatement("insert into users (name,...) values ("+newName+",...)").executeUpdate(); ///and inserts..
}
does the select query return the last inserted value
or
it returns the max column in the table before I start the loop ?
First, to make sure you see all changes on the database immediately prefer TransactionIsolation of READ_UNCOMMITED over using auto commit. Alternatively using auto commit everywhere would do the job, too.
Once you made sure you see every db change immediately, the database will send you the maximum user from some time during the selects execution. But once you actually receive the result there might be additional users created by others threads. Thus this will only work for a single thread working and most likely that doesn't make any sense nowadays.
TL:DR
No, don't do it!

Categories

Resources