I've stack over one small thing:
I have two tables in database, which are related - User and UserReference.
In UserReference i have field userid, which is related to id in User.
i have query to mysql with join left:
"FROM User as user left join fetch user.userReferences WHERE login='"+login+"' or email='"+login+"' AND password = '" +password+ "'" ;
The query is ok and i get results.
I send the results to controller, changing it into list: query.list();
In controller i receive the results and push it into user list.
From the user list i can get info from table User
In table User there is:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
public Set<UserReference> getUserReferences() {
return this.userReferences;
}
And now - i want to get data from table UserReference which are in user list, becouse my query have JOIN.
How can i do it?
i was trying to do something like this:
List<UserReference> userReference = (List<UserReference>) user.get(0).getUserReferences();
System.out.println(userReference.get(0).getAge());
But it doesn't work.
Can you help me ?
You can't cast a Set to a List, iterate over the Set to get userRefences instead.
Related
I have these entities (is an example because i cant share real name entities):
#Entity
public class User { #Id private BigDecimal id; private String name, private Color favouriteColor }
#Entity
public class Color { #Id private Long colorId; private String colorName;}
In the table I have this data:
USER
ID|NAME|FavColor
1 |John| 1
2 |Sarah| 2
3 |Mike| 1
COLOR
1|Red
2|Blue
Now I want make a query that recover all my user data without select Color entity, only its ids.
#Query("new myDto(u.iduser,u.username,u.favcolor) from user u where favcolor in :listcolors")
This makes me an query of the two tables, I want a unique query because i dont need color entities, only the ids.
--
Other option that I am testing is making a implementation of a nativequery like this:
final List<MyDTO> result = new ArrayList<>();
Query q = entityManager.createNativeQuery("SELECT " +
" USER_ID, " +
" USER_NAME, " +
" FAV_COLOR " + +
"FROM USER " +
"WHERE FAV_COLOR IN (?)");
q.setParameter(1, colors.toString().replace("[","").replace("]",""));
Long TRUE = new Long(1L);
final List<Object[]> resultList = q.getResultList();
for (Object[] objects : resultList) {
MyDTOdto = new MyDTO();
dto.userId(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
dto.userName(((((String) objects[0]) != null) ? ((String) objects[0]).longValue() : null));
dto.favColor(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
result.add(dto);
}
return result;
In this case, I am getting error code (ORA-1722 - Number Not valid). I don't know what I can test now. Some ideas? Thanks
I am guessing you have issues with the SQL generated and your use of the inner join: when you call "u.favcolor" in the select clause, you are telling JPA to perform an inner join from User to Color based on the favcolor relationship. As favcolor is a Color reference, you are going to get the full color row, where as your native query implies you just want the foreign key value. If all you want is the fk/ID value from Color, the query should be:
"SELECT new myDto(u.iduser, u.username, color.id) FROM user u join u.favcolor color WHERE color.id in :listcolors"
This still might perform an inner join from user to color, but it should be in a single statement.
If you want to ensure you avoid the join:
Use EclipseLink's COLUMN JPQL extension to access the foreign key column directly. Something like:
"SELECT new myDto(u.iduser, u.username, COLUMN('FAV_COLOR', u) FROM user u WHERE COLUMN('FAV_COLOR', u) in :listcolors"
Use EclipseLink native query key functionality to access the "FAV_COLOR" foreign key column in the USER table directly for your JPQL queries. This requires a descriptor customizer to access, but allows you to use the foreign key value in JPQL queries directly without having to map it, and without the COLUMN mechanism tying your JPQL queries to a particular database table detail. This would allow a query of the form:
"SELECT new myDto(u.iduser, u.username, u.favColorVal FROM user u join u.favcolor color WHERE u.favColorVal in :listcolors"
Just map the FAV_COLOR as a basic mapping, in addition to the existing favColor reference mapping (or replacing it if you want):
#Basic
#Column(name="FAV_COLOR", updatable=false, insertable=false)
BigDecimal favColorId
This then allows you to use query "SELECT new myDto(u.iduser, u.username, u.favColorId FROM user u join u.favColorId color WHERE u.favColorId in :listcolors" to the same effect, but you can also just return the User instance (marking favColor as lazy and not serializable) as it will have the same data anyway.
I have a class ReleaseNote saved in the table RELEASE_NOTES and a table RELEASE_NOTE_USER_READ with the columns RELEASE_NOTE_ID and USER_ID where I want to save which users have already read a releaseNote, so I don't show it again.
Since we are using a microservice architekture I don't have a user object in that microservice and don't want to add one. Although it won't be a problem to add a field usersRead to the ReleaseNote which contains the userId of all the users who have read the releaseNote.
I need to perform two actions:
Pass a list of releaseNoteIds to be saved in the table for a given userId, so I can keep track of the releaseNotes a user has read.
Select all releaseNotes a user has not read. The SQL-Statement for this would look like:
SELECT * FROM RELEASE_NOTES WHERE ID NOT IN (SELECT RELEASE_NOTE_ID FROM RELEASE_NOTE_USER_READ WHERE USER_ID = :userId)
How can I achieve this using the EntityManager or Hibernate specific functionality?
Found the solution myself. Add field Set usersRead to ReleaseNote and annotate like the following:
#ElementCollection
#CollectionTable(name = "RELEASE_NOTES_USER_READ",
joinColumns = #JoinColumn(name = "RELEASE_NOTE_ID"))
#Column(name = "USER_ID", table = "RELEASE_NOTES_USER_READ")
private Set<Integer> usersRead = new HashSet<>();
I've got an issue with JPA, I need to return a list of users but I always get the user the id is from
This one is working correctly and returns the users that you are following:
#NamedQuery(name = "User.findByFollowing",
query = "select User from User user join user.followers f where f.id=:id"),
This query always returns the user of the id parameter (param=1 returns user1 instead of all the users you are followed by)
#NamedQuery(name = "User.findFollower",
query = "select User, f from User user join user.followers f where user.id=:id")
The table looks like this, both columns are id's of the user table.
As you can see:
user4 got 2 followers
user3 got 1 follower
user 2 is following 2 users
user 1 is following 1 user
This is the user table
The follower table is generated by JPA with a arraylist
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<User> followers = new ArrayList();
Now you've got some background info I will get to the point.
As user 2 I can see that i am following user3 and user 4. But if I am user 3 I can't see that user2 is following me (This always returns user3 in some way)
If you need more information feel free to ask
Why don't you do "select u from User u where u.id = :id" and access the followers via u.getFollowers() in your java code? You don't explicitly need the join if your entities have the relationship.
I have an entity, called "Client", which contains a List users.
public class Client {
#OneToMany(fetch = FetchType.EAGER, mappedBy="client")
private List<User> users;
}
I want to write a query which does something like:
SELECT *
FROM Client client
JOIN Users user
ON user.client_id = client.client_id
WHERE ( user.name LIKE '%name%' AND user.role = 'ADMINISTRATOR' )
Does anyone know how to do with using Specifications?
Normally, if there was one user, I would do something like this below. But since we have here a List I am not sure how to approach this situation.
Path<User> user = root.<User> get("user");
queryPredicates.add(cb.like(cb.upper(user .<String>get("name")), getLikePattern(queryString)));
queryPredicates.add(cb.like(cb.upper(user .<String>get("role")), "ADMINISTRATOR));
If I wanted to compare an equal, I could construct a User object and do something like this:
User user = new User();
// set properties
queryPredicates.add(cb.isMember(user, root.<Collection<User>>get("users")));
I could do something like:
Path<List<User>> users = root.<List<User>>get("users");
But then what?
Thanks,
Joachim
The solution could be on user side, i.e. in UserRepository:
findByClientAndRoleAndNameLike(Client client, String role, String name)
You can use JPA entity manager query to do something like that :
List<Client> clients = (List<Client>) entityManager
.createQuery(
"select c from Client c join c.users u where u.role='ADMISTRATOR' and u.name like :name")
.setParameter("name", "foo").getResultList();
You can find more about this here
I have 2 tables Asset and Asset_Dist_Types. Asset is parent and Asset_Dist_Types is a child table. Asset_Dist_Types is having 2 columns asset_id and lkp_dist_type where asset_id is the primary key in Asset table. In Asset_Dist_Types it is a many to many (one asset_id can have multiple lkp_dist_type entries.) In java, we have entity class only for Asset table. In that for Asset_Dist_Type, they have mentioned it as collection of elements. In Asset.java, entry for Asset_Dist_Type is as follows.
#CollectionOfElements
#JoinTable(name = "ASSET_DIST_TYPE", joinColumns = #JoinColumn(name="ASSET_ID"))
#Column(name="LKP_DIST_TYPE")
private Set<Integer> distTypes = new LinkedHashSet<Integer>(0);
Now I would like to update Asset_Dist_Type table's lkp_dist_type column. I have list of asset id's. I have written following query to update it.
int hql = entityManager.createQuery(
"update Asset a set a.distTypes = :distTypeParamId where a.assetId in (:assetIdParam)")
.setParameter("distTypeParamId", distTypeList)
.setParameter("assetIdParam", assetIdListToUpdateLOB)
.executeUpdate();
But this is throwing
javax.persistence.PersistenceException:
org.hibernate.exception.GenericJDBCException: could not execute update query.
Since I am new to hibernate I am not getting what is the solution. Can someone please help me?
Solved it by following a different way.. I got list of asset id's and list of distribution types. I iterated over the list of asset id's and for each asset id I added list of distribution types and flushed it. It is working now..!
After getting list of asset id's
for(int i=0;i<assetIdListToUpdateLOB.size();i++){
int assetId = assetIdListToUpdateLOB.get(i);
System.out.println(assetId);
List<Asset> assetDetailsList = entityManager
.createQuery(
"select distinct asset from Asset asset "
+ "left join fetch asset.distTypes dt "
+ "where asset.assetId = :assetIdParam")
.setParameter("assetIdParam", assetId).getResultList();
if(assetDetailsList.size()>0){
this.asset = assetDetailsList.get(0);
asset.getDistTypes().clear();
asset.getDistTypes().addAll(selectedDistributionTypes);
entityManager.flush();
}
}