I have following entity:
public final class Stock implements Serializable {
#JsonIgnore
#ManyToMany(mappedBy = "stocks", fetch = FetchType.LAZY)
private Set<User> users = new HashSet<>();
[Other fileds]
[getters/setters]
}
And i would like write query in jpql to get top5 Stock entity based on size of set users. So far i write native query in sql and it looks like:
SELECT s.ticker, COUNT(s.ticker)
FROM t_stock s INNER JOIN t_user_stocks us ON s.id = us.stock_id
INNER JOIN t_user u on us.user_id = u.id GROUP BY s.ticker ORDER BY count DESC
And i want a jqpl query which return top 5 stocks entity. Could someone help me?
Assuming your entity is mapped as follows.
#Entity
public class Stock {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column
private String ticker;
#JsonIgnore
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "stock_user", joinColumns = { #JoinColumn(name = "STOCK_ID", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "USER_ID", nullable = false, updatable = false) })
private Set<User> users = new HashSet<User>();
}
I did the following using native SQL to get the result.If you insist on using JPQL, the answer here is your friend.
public interface StockRepository extends JpaRepository<Stock, Integer> {
#Query(value = "SELECT s.ticker, COUNT(s.ticker) FROM stock s INNER JOIN "
+ "stock_user us ON s.id = us.stock_id INNER JOIN user u on us.user_id = u.id GROUP BY s.ticker order by count(*) desc limit 1", nativeQuery = true)
public List<Object[]> findStock();
}
Related
I'm trying to write to a Query in JPA,and Query is working fine but result is not correct.
Mapping in User.java
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable( name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
Entity Role.java
#Entity
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Enumerated(EnumType.STRING)
#Column(length = 20)
private ERole name;
}
Enum file
public enum ERole {
USER,
GUEST,
ADMIN,
USER_HANDLER,
TOURNAMENT_HANDLER,
CHALLENGE_HANDLER,
CHAMPIONSHIP_HANDLER
}
and Join Query in UserRepository.java
#Query("select u.userId from User u LEFT JOIN Role r ON u.id = r.id AND r.name = 'ADMIN' OR r.name = 'USER_HANDLER'")
List<Long> findSubAdmins();
Result: I'm printing size of List in console
Expected - 5
Getting - 8 (8 is the total no. of record in join table)
#Query("select distinct(u.id) from User u INNER JOIN u.roles r ON r.name IN ('ADMIN', 'USER_HANDLER')")
List<Long> findSubAdmins();
I have two entities User and Role. Each user can have multiple roles.
User class
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "user_role",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
}
Role class:
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
private String name;
}
So a new joined table is being created called: user_role
I want to create a query for returning a list of users with role_id of 4, for example.
The query that I already tried:
#Override
public List<User> getArtists() {
return em.createQuery(
"from User u, Role r where u.roles='4'",
User.class
).getResultList();
}
How can I fix this query in order to retrieve a list of users with role_id of 4?
You can do something like this:
List<User> users = em.createQuery(
"select distinct u from User u join fetch u.roles rl where rl.id = :id",
User.class)
.setHint( QueryHints.HINT_PASS_DISTINCT_THROUGH, false )
.setParameter("id", 1L)
.getResultList();
The QueryHints.HINT_PASS_DISTINCT_THROUGH is added as an additional performance optimization. But please note that this optimization will work only with hibernate 5.2.2.Final ... 5.2.11.Final. It was broken in the 5.2.12.Final.
If I were you, I will get the benfit of using SpringdataJpa with hibernate and just use this statment :
If you don't want to use query :
List<User> findByRoles_Id(Long id);
In your User Repository :
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByRoles_Id(Long id);
}
I have tried many.
But the cause could not be found.
I need your help
CardNews Entity
#Entity
#Table(name = "card_news", schema = "pikeul", indexes = #Index(name = "IDX_CARD_NEWS_1", columnList = "user_seq, reg_date"))
public class CardNews implements Serializable {
private static final long serialVersionUID = 8912318097356401738L;
#Id
#Column(name = "card_seq", nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long cardSeq;
#Column(name = "user_seq", nullable = false)
private long userSeq;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_seq", referencedColumnName = "user_seq", insertable = false, updatable = false, foreignKey = #ForeignKey(name = "none"))
private User user;
#Fetch(FetchMode.SELECT)
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns(value = {
#JoinColumn(name = "card_seq", referencedColumnName = "card_seq", insertable = false, updatable = false),
#JoinColumn(name = "user_seq", referencedColumnName = "user_seq", insertable = false, updatable = false)
}, foreignKey = #ForeignKey(name = "none"))
private LikeCard likeCard = new LikeCard();
// Getter & Setter
}
CardLike Entity
#Entity
#Table(name = "card_like", schema = "pikeul")
public class LikeCard implements Serializable {
#EmbeddedId
private LikeCardPk pk;
public LikeCard(){
this.pk = new LikeCardPk(0, 0);
}
public LikeCard(LikeCardPk pk) {
this.pk = pk;
}
public LikeCardPk getPk() {
return pk;
}
public void setPk(LikeCardPk pk) {
this.pk = pk;
}
}
Spring Data JPA Query Case-1
#EntityGraph(attributePaths = {"user", "likeCard"})
#Query( "SELECT card FROM CardNews card " +
"JOIN card.user user ON user.useYn = true " +
"LEFT JOIN card.likeCard likeCard ON likeCard.pk.userSeq = ?#{principal.user.userSeq ?: '0'} " +
"WHERE card.cardSeq = :cardSeq AND card.useYn = true")
Spring Data JPA Query Case-2
#Query( "SELECT card, user, likeCard FROM CardNews card " +
"JOIN card.user user ON user.useYn = true " +
"LEFT JOIN card.likeCard likeCard ON likeCard.pk.userSeq = ?#{principal.user.userSeq ?: '0'} " +
"WHERE card.cardSeq = :cardSeq AND card.useYn = true")
The problem is as follows. When inquiring CardLike Entity through ManyToOne in CardNews Entity, CardLike Entity exists or does not exist.
CardLike may be null when fetching data through left join fetch when executing Query for Case1 and Case2.
Look at the log.
Hibernate:
select
cardnews0_.card_seq as card_seq1_5_0_,
user1_.user_seq as user_seq1_12_1_,
likecard2_.card_seq as card_seq1_4_2_,
likecard2_.user_seq as user_seq2_4_2_,
cardnews0_.contents as contents2_5_0_,
cardnews0_.game_type as game_typ3_5_0_,
cardnews0_.hash_tag as hash_tag4_5_0_,
cardnews0_.user_seq as user_seq8_5_0_,
cardnews0_.like_count as like_cou5_5_0_,
cardnews0_.reg_date as reg_date6_5_0_,
cardnews0_.use_yn as use_yn7_5_0_,
user1_.agree_date as agree_da2_12_1_,
user1_.agree_yn as agree_yn3_12_1_,
user1_.email as email4_12_1_,
user1_.mod_date as mod_date5_12_1_,
user1_.nickname as nickname6_12_1_,
user1_.night_push_yn as night_pu7_12_1_,
user1_.profile_image as profile_8_12_1_,
user1_.provider as provider9_12_1_,
user1_.provider_id as provide10_12_1_,
user1_.push_date as push_da11_12_1_,
user1_.push_yn as push_yn12_12_1_,
user1_.reg_date as reg_dat13_12_1_,
user1_.thumbnail_image as thumbna14_12_1_,
user1_.use_yn as use_yn15_12_1_
from
card_news cardnews0_
inner join
enter_user user1_
on cardnews0_.user_seq=user1_.user_seq
and (
user1_.use_yn='Y'
)
left outer join
card_like likecard2_
on cardnews0_.card_seq=likecard2_.card_seq
and cardnews0_.user_seq=likecard2_.user_seq
and (
likecard2_.user_seq=?
)
where
cardnews0_.card_seq=?
and cardnews0_.use_yn='Y'
Hibernate:
select
likecard0_.card_seq as card_seq1_4_0_,
likecard0_.user_seq as user_seq2_4_0_
from
card_like likecard0_
where
likecard0_.card_seq=?
and likecard0_.user_seq=?
As above, if data is retrieved through left join fetch but CardLike Entity does not exist, you can see the log to select again.
If this is the result of the list, select 1 + N.
I tried to downgrade but the result was the same
The development environment is as follows
Spring 5.0.4, Spring-Data-JPA 2.0.4, Hibernate 5.2.13
I am new to Hibernate and really need help from you guys....
I have following class: UserActionPerUserResult
#Entity
#Table(name = "user_action_per_user_result")
public class UserActionPerUserResult {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "user_email", nullable = false)
private String userEmail;
#ManyToOne
#JoinColumn(name = "user_action_id", nullable = false)
private UserAction userAction;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name="user_action_per_user_result_email_message",
joinColumns={#JoinColumn(name="user_action_per_user_result_id", referencedColumnName="id")},
inverseJoinColumns={#JoinColumn(name="email_message_id", referencedColumnName="id")})
#JsonIgnore
private List<EmailMessage> emailMessages;
....getters/setter....
}
In MYSQL, the UserActionPerUserResult is one table and for email Messages, there is another table called as UserActionPerUserResultEmailMessage which has email messages associate with id of the table UserActionPerUserResult.
I have all the data stored in the MySQL table, however I am not able to query it. I need to write a query to fetch the list of emailMessages. I am trying the following, but it is throwing exception.
TypedQuery<UserActionPerUserResult> messagesQuery = entityManager.createQuery(
"SELECT e from UserActionPerUserResult e JOIN UserActionPerUserResult.emailMessages e1 WHERE e.id = 1 and e.userAction = 1", UserActionPerUserResult.class);
List<UserActionPerUserResult> resultList = messagesQuery.getResultList();
Try writing the query like this:
TypedQuery<UserActionPerUserResult> messagesQuery = entityManager.createQuery(
"SELECT e from UserActionPerUserResult e JOIN FETCH e.emailMessages em WHERE e.id = 1 and e.userAction.id = 1", UserActionPerUserResult.class);
List<UserActionPerUserResult> resultList = messagesQuery.getResultList();
The join is using the root entity alias
The userAction.id is used against userAction, when matching against a numerical value
I’m using JPA 2.0, Hibernate 4.1.0.Final, and MySQL 5.5.37. I have the following entities
#Entity
#Table(name = "user_subscription",
uniqueConstraints = { #UniqueConstraint(columnNames = { "USER_ID", “SUBSCRIPTION_ID" }) }
)
public class UserSubscription
{
#Id
#Column(name = "ID")
#GeneratedValue(generator = "uuid-strategy")
private String id;
#ManyToOne
#JoinColumn(name = "USER_ID", nullable = false, updatable = true)
private User user;
#ManyToOne
#JoinColumn(name = “SUBSCRIPTION_ID", nullable = false, updatable = true)
private Subscription subscription;
and
#Entity
#Table(name = "Subscription")
public class Subscription implements Serializable
{
#Id
#Column(name = "ID")
#GeneratedValue(generator = "uuid-strategy")
private String id;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PRODUCT_ID")
#NotNull
private Product product;
Without altering the entities, how do I construct a JPA CriteriaBuilder query in which I look for User entities that do not have a particular Subscription entity “A”, but have other subscription entities that match the same product as entity “A”? I have tried this to no avail …
public List<User> findUsersWithSubscriptions(Subscription Subscription)
{
final List<User> results = new ArrayList<User>();
final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
final CriteriaQuery<UserSubscription> criteria = builder.createQuery(UserSubscription.class);
final Root<UserSubscription> root = criteria.from(UserSubscription.class);
Join<UserSubscription, Subscription> SubscriptionRoot = root.join(UserSubscription_.subscription);
criteria.select(root).where(builder.equal(root.get(UserSubscription_.Subscription).get(Subscription_.product),subscription.getProduct()),
builder.notEqual(root.get(UserSubscription_.subscription), subscription));
I thought if I could build a SetJoin from the user -> subscription entities, I could say something like “not.in”, but I’m not sure how to do that given the constraints.
Edit: This is the SQL produced by Vlad's post:
SELECT user1_.id AS id97_,
user1_.creator_id AS CREATOR15_97_,
user1_.dob AS DOB97_,
user1_.enabled AS ENABLED97_,
user1_.expiration AS EXPIRATION97_,
user1_.first_name AS first5_97_,
user1_.grade_id AS GRADE16_97_,
user1_.incorrect_logins AS INCORRECT6_97_,
user1_.last_name AS last7_97_,
user1_.middle_name AS middle8_97_,
user1_.organization_id AS organiz17_97_,
user1_.password AS password97_,
user1_.reset_state AS RESET10_97_,
user1_.salutation AS salutation97_,
user1_.temporary_password AS temporary12_97_,
user1_.url AS url97_,
user1_.user_demographic_info_id AS USER18_97_,
user1_.user_name AS user14_97_
FROM sb_user_subscription subscription0_
INNER JOIN sb_user user1_
ON subscription0_.user_id = user1_.id
INNER JOIN cb_subscription subscription2_
ON subscription0_.subscription_id = subscription2_.id
INNER JOIN sb_product product3_
ON subscription2_.product_id = product3_.id
AND product3_.id = ?
AND subscription2_.id <>?
Check this query:
final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
final CriteriaQuery<User> criteria = builder.createQuery(User.class);
final Root<UserSubscription> root = criteria.from(UserSubscription.class);
Join<UserSubscription, User> userJoin = root.join(UserSubscription_.user);
Join<UserSubscription, Subscription> subscriptionJoin = root.join(UserSubscription_.subscription);
Join<Subscription, Product> productJoin = subscriptionJoin.join(Subscription_.product);
criteria
.select(userJoin)
.where(cb.and(
builder.equal(productJoin, subscription.getProduct()),
builder.notEqual(subscriptionJoin, subscription)
);
return entityManager.createQuery(criteria).getResultList();
The output query looks fine and it should select Users with a given subscription.product and with a different subscription than the product parent's one.
You could try it in your SQL console, but it looks fine and it validates the initial requirement:
that do not have a particular Subscription entity “A”, but have other
subscription entities that match the same product as entity “A”