I want to make a JPQL query with a collection of non entities. This is my Table entity :
#Entity
#Table(name = "ct_table")
public class Table {
...
#CollectionOfElements(fetch = FetchType.EAGER)
#JoinTable(name = "ct_table_result", joinColumns = #JoinColumn(name = "tableId"))
#MapKey(columns = { #Column(name = "label") })
#Column(name = "value")
private Map<String, String> tableResults;
...
then I try to make a query like this
select count(*) from table where table.tableResults['somekey'].value='somevalue'
but I get the following exception:
Cannot create element join for a collection of non-entities!
Any suggestion??
thanks for your time
EDIT:
I use JPA 1 and hibernate 3.3. Default libraries in JBoss 5
The JPA 2 spec (page 139) defines the KEY() and VALUE() functions to access the key and the value of a map-valued element collection:
select count(t.id) from Table t
where KEY(t.tableResults) = 'somekey' and VALUE(t.tableResults) = 'somevalue'
Related
For simplicity I'll chop the tables down quite a bit
Given the tables REPORT_DOWNLOAD, REPORT
REPORT has ID, NAME
REPORT_DOWNLOAD has ID, FK_REPORT_ID
I essentially want to build the query:
SELECT R.NAME, RD.ID FROM REPORT_DOWNLOAD RD, REPORT R WHERE
RD.FK_REPORT_ID = R.ID
My entity for REPORT_DOWNLOAD essentially looks like
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "FK_REPORT_ID", referencedColumnName = "ID", nullable = false)
private ReportOrm report;
But that queries the whole REPORT table. Is there a way to reference just the NAME column from the entity?
#SomeAnnotationThatMagicallyPulls("FK_REPORT_ID", "NAME")
private String reportName;
I feel like there must be some Hibernate / JPA magic here that I could use
In a spring boot + JPA applition, I have a user table and a item table with a ManyToMany relationship. The users can "follow" any Item element, in a twitter/facebook style to get the posts related to that item, get notificacions when an item change, etc.
The classes are like this, very simple way:
UserEntity.java
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Size(max = 50)
#Column(name = "username", length = 50)
private String username;
#ManyToMany
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#JoinTable(name = "user_follow_item",
joinColumns = #JoinColumn(name="user_id", referencedColumnName="id"),
inverseJoinColumns = #JoinColumn(name="follow_item_id", referencedColumnName="id"))
private Set<Items> followItems = new HashSet<>();
ItemEntity.java
#ManyToMany(mappedBy = "followItems")
private Set<User> followUsers = new HashSet<>();
The query is made with JpaRepository repository classes and exposed in spring boot throught a #RestController class and all works just fine.
The question is, in a query looking for items by id, it is possible to get if the current user (the logged user) is following the item? All the data in one single query. With this query I get the item info, but I don't know how to get if the user if following the item:
#Query("select item from Item item left join item.followUsers userFollow on userFollow.login = ?#{principal.username} where item.id = :id ")
Item itemWithCurrentUserFollows(#Param("id") Long id);
The query in native SQL is something like this (when i get data in "follow" part I know that the user is following the item) but I don't know how to realice this in a JPA query:
SELECT * FROM item left join (user user join user_follow_item follow) on user.id = follow.user_id and follow.follow_item_id = item.id and user.username = 'mockUser' where item.id = 1;
Any ideas are welcome (#Formula, a extra boolean value with this info, etc...)
Many Thanks!
I thought I understood hibernate's fetching strategies, but it seems I was wrong.
So, I have an namedNativeQuery:
#NamedNativeQueries({
#NamedNativeQuery(
name = "getTest",
resultClass = ArticleOnDate.class,
query = "SELECT `a`.`id` AS `article_id`, `a`.`name` AS `name`, `b`.`price` AS `price` FROM article a LEFT JOIN price b ON (a.id = b.article_id) WHERE a.date <= :date"
)
})
#Entity()
#Immutable
public class ArtikelOnDate implements Serializable {
#Id
#OneToOne
#JoinColumn(name = "article_id")
private Article article;
...
}
Then I call it:
Query query = session.getNamedQuery("getTest").setDate("date", date);
List<ArticleOnDate> list = (List<ArticleOnDate>) query.list();
The query returns thousand of entities... Well, ok, but after that query hibernate queries thousand other queries:
Hibernate:
select
article0_.id as id1_0_0_,
article0_.bereich as name2_0_0_,
price1_.price as price1_14_1_
from
article artikel0_
where
artikel0_.id=?
Ok, that's logic, because the #OneToOne relation is fetched eagerly. I don't want to fetch it lazy, so I want a batch fetching strategy.
I tried to annotate the Article property but it didn't work:
#Id
#OneToOne
#JoinColumn(name = "article_id")
#BatchSize(size=100)
private Article article;
So what can I do to fetch the relation in a batch?
I have folowing property in my hibenrate entity class:
#MapKeyJoinColumn(name = "language_code")
#LazyCollection(LazyCollectionOption.EXTRA)
#ElementCollection(fetch = FetchType.LAZY)
#CollectionTable(name = "text_translations", joinColumns = #JoinColumn(name = "text_id"))
private Map<Language, String> translations = new HashMap<>();
Now I want to query this entity and filter content of map by user's language (i.e. by map's key). I have folowing join in my query:
StringPath titleTran = new StringPath("title_tran");
from(entity).
.leftJoin(entity.translations, titleTran).fetch().where(?mapKey?.eq(userLanguage));
What I need is ?mapKey? to by path to language of titleTran path. Is this somehow possible in QueryDsl?
If you want to search for a given Map key, you can use the following HQL query:
select me
from MyEntity me
join me.translations tr
where
index(tr) = :lang
or with JPQL:
select me
from MyEntity me
join me.translations tr
where
key(tr) = :lang
In Querydsl JPA the following works
query.from(me).where(me.translations.containsKey(lang)).list(me);
Suppose I have the following entity which models a subscriber and uses a CollectionTable to model a list of subscriptions like so:
#Entity
#Table(name = "SUBSCRIBER")
public class Subscriber {
#ElementCollection
#CollectionTable(name = "PERSON_ORG_SUBSCRIPTIONS",
joinColumns = { #JoinColumn( name = "PERSON_ID", referencedColumnName = "PERSON_ID" ),
#JoinColumn( name = "ORG_ID", referencedColumnName = "ORG_ID" ) } )
#Column(name = "SUBSCRIPTION_NAME")
protected Set<String> _subscriptionNames;
}
So this creates a table with columns for PERSON_ID, ORG_ID and SUBSCRIPTION_NAME.
I'm trying to create a database index on the SUBSCRIPTION_NAME column. But if I put the following annotation on _subscriptionNames:
#org.hibernate.annotations.Index( name="subscription_idx", columnNames={"SUBSCRIPTION_NAMES"} )
I get an exception:
org.hibernate.MappingException: Unable to find logical column name from physical name null in table SUBSCRIBER
I also tried using the org.hibernate.annotations.Table annotation on the Subscriber entity, but there does not seem to be a way to have it reference the PERSON_ORG_SUBSCRIPTIONS table.
I'm using Hibernate 3.5.3 and PostgreSQL 9.0.
Is the column with name "SUBSCRIPTION_NAME" present in the table SUBSCRIBER?
Are you planning to create index on table from the code? You should propably use hibernate.hbm2ddl.auto=create