How to test if Enum value is in EnumSet using JPQL - java

I have a property as follows:
#Entity
class Project implements Serializable {
#Convert(converter = TypeFlattener.class)
#Column(name = "assignable_types")
private EnumSet<Type> assignableTypes;
The point of the TypeFlattener is that I want to avoid normalization for a simple list, so basically it converts the EnumSet to/from a simple String with comma separated values matching the Enum.name()
Now the question is how can I filter only Projects that have the a specific Type in assignableTypes?
My best approach would be something like that:
#NamedQuery(
name="Project.findByType",
query="SELECT p FROM Project p WHERE :t IN p.assignableTypes"
)
What do I pass in for :t? The String version as follows? Can I even do this?
q.setParameter("id", "MAJOR");

The converter does not matter here as he only affects the database representation. The below query using MEMBER OF should work.
TypedQuery<Project> query = em.createQuery(
"SELECT p FROM Project p WHERE :type MEMBER OF p.assignableTypes", Project.class);
query.setParameter("type", Type.ONE);
List<Project> resultMemberOf = query.getResultList();

Related

Is it possible to query with list of objects using JPA like foreach tag?

Let's say I have a query like this:
Query object
public class myObject {
private String code;
private String name;
}
query method
#Query(nativeQuery = true,value = "...")
findByAcodeAndBname(List<MyObject> queryObject);
Pseudocode of the query
select a.code, b.name from tableA a
left join table b on a.column = b.column
where a.code = ${} b.name = ${}
Since it could cause performance issues just simply using foreach code in Java to do the query, how do I map every pair of a.code and b.name using native JPA query like mybatis foreach tag? Or is it posssible?
I think you don't need native query here, because the costs of querying data from the database and transfering it over network are higher than any related Java operations.
Instead of native query you can use JPQL query, e.g.
#Query("select new com.tsypanov.domain.HasIdAndNameDto(e.id, e.name)" +
" from ManyFieldsEntity e " +
"where e.name = :name")
List<HasIdAndName> findAllByNameUsingDto(#Param("name") String name);
Here we call constructor of DTO from JPQL query passing the fields from our entity. The DTO class must have the specified constructor:
#RequiredArgsConstructor
public class HasIdAndNameDto {
private final Long id;
private final String name;
}

How to select an attribute of a list elements in jpql

I have a Project entity, containing a list of its creators,
public class Project implements Serializable {
#ManyToMany
private List<Creator> creator;
I need a method with a parameter creator id, returning a list of the projects created by that creator, here is my idea
public List<Project> MyOwnProjects(int idcreator){
String jpql= "select p from Project p where p.creator.get(i).getCode()= :idcreator";
Query query= em.createQuery(jpql);
query.setParameter("idcreator", idcreator);
return (List<Project>)query.getResultList();
}
This query is not valid of course, How can I do that ?
Unless you can't modify the mapping, I would do it the other way around : add a #ManyToMany association in your Creator entity (using MappedBy), then something like this (my JPQL is quite rusty)
"select p from creator left join fetch creator.project p where creator.id = :idcreator "

Hibernate calculated collection #Formula

is it possible to have and Entity with a field calculated using Formula when the field is a Collection (let's say it's a Set)?
Here's the dummy example of what I'm trying to achive:
#Formula(value =
"SELECT NEW com.example.entity.Person(p.name, p.age) FROM Person p")
lateinit var people :Set<Person>
From the JavaDoc for #Formula:
Defines a formula (derived value) which is a SQL fragment ...
You have to think of the fragment you write as an replacement in the select statement:
SELECT (formulaValue) AS propertyName FROM ....
Everything you can write into formulaValue can be used in #Formula.
Your example is not a valid SQL fragment and as you can see, it is not possible to return more than one value from a #Formula.
But you could use #Subselect and a wrapper object instead:
#Entity
#Subselect("SELECT name, age FROM Person p")
public class PersonWrapper {
#Id
private String name;
private int age;
}
(in Java, as I'm not aware of the correct syntax of Kotlin)
If you really need the collection of these values in another entity, you need something to join on (which is missing in your example) and use that in an #OneToMany or #ManyToMany. Otherwise there is no use to have all these values in your entity, as all entities would have the same collection.

manage return type hibernate

I'm using native query to get data from database and add them into an object that content float values like:
select tons, delivered_tons from contract where id = 1
and using createSQLQuery() to execute the query
and return an object array like:
Object[] result = (Object[])query.uniqueResult();
and cast them into my object
A a = new A((Float)result[0],(Float)result[1]);
The problem is that I can't know the return type of the query (float or double). So do hibernate has any method to control the return type?
If you used HQL instead os SQL, Hibernate would use the types that you chose to map the columns in your entity:
Assuming you have a Contract entity containing these fields:
#Entity
public class Contract {
#Column(name = "tons")
private Float tons;
#Column(name = "delivered_tons")
private Float deliveredTons;
...
}
You would simply execute the HQL query
select c.tons, c.deliveredTons from Contract c where c.id = :id
and you would be sure to get an array containing two Floats.
That said, for such a simple query, why don't you just use
Contract c = (Contract) session.get(Contract.class, id);
and then get the fields you want from the entity?

Hibernate Criteria API - adding a criterion: string should be in collection

I have to following entity object
#Entity
public class Foobar {
...
private List<String> uuids;
...
}
Now I'd like to make a criteria query which would fetch all Foobar pojos whose uuids list contains the string "abc123", I'm just not sure how to make the appropriate criterion.
I assume you are using a version of Hibernate that implements JPA 2.0. Here's a JPA 2.0 solution that should work with any compliant implementation.
Please annotate uuids with JPA's #ElementCollection annotation. Don't use Hibernate's #CollectionOfElements as mentioned in some of the other answer comments. The latter has equivalent functionality but is being deprecated.
Foobar.java will look approximately like this:
#Entity
public class Foobar implements Serializable {
// You might have some other id
#Id
private Long id;
#ElementCollection
private List<String> uuids;
// Getters/Setters, serialVersionUID, ...
}
Here's how you can build a CriteriaQuery to select all Foobars whose uuids contain "abc123".
public void getFoobars() {
{
EntityManager em = ... // EM by injection, EntityManagerFactory, whatever
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<Foobar> cq = b.createQuery(Foobar.class);
Root<Foobar> foobar = cq.from(Foobar.class);
TypedQuery<Foobar> q = em.createQuery(
cq.select(foobar)
.where(b.isMember("abc123", foobar.<List<String>>get("uuids"))));
for (Foobar f : q.getResultList()) {
// Do stuff with f, which will have "abc123" in uuids
}
}
I made a self-contained proof-of-concept program while playing with this. I can't push it out right now. Please comment if you want the POC pushed to github.
I know this is old question, but I have just encountered this issue and found solution.
If you want to use Hibernate Criteria you can join your uuids collection and use its property elements to match elements. Just like that:
session.createCriteria(Foobar.class)
.createAlias("uuids", "uuids")
.add(Restrictions.eq("uuids.elements", "MyUUID"))
.list()
You could use a Query as in the example below or you could convert this to a NamedQuery. Unfortunately there doesn't seem to be a way to do this with Criteria.
List<Foobar> result = session
.createQuery("from Foobar f join f.uuids u where u =: mytest")
.setString("mytest", "acb123")
.list();
I've found this post from one year ago, and I've made this method, if it can help anybody with the same problem I had a few hours ago.
Public List<EntityObject> getHasString(String string) {
return getSession().createCriteria(EntityObject.class)
.add(Restriction.like("property-name", string, MatchMode.ANYWHERE).ignoreCase();
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
Made the same with a group of strings too.
public List<EntityObject> getByStringList(String[] tab) {
Criterion c = Restrictions.like("property-name", tab[tab.length-1], MatchMode.ANYWHERE).ignoreCase();
if(tab.length > 1) {
for(int i=tab.length-2; i >= 0 ; i--) {
c = Restrictions.or(Restrictions.like("property-name",tab[i], MatchMode.ANYWHERE).ignoreCase(), c);
}
}
return getSession().createCriteria(EntityObject.class)
.add(c)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
}
It works with "or" statements, but can easily be replaced by "and" statements.
What you are asking is not supported out of the box by hibernate. See http://opensource.atlassian.com/projects/hibernate/browse/HHH-869
Here is a workaround available in the jira ticket :
entityCriteria.add(Restrictions.sqlRestriction(
"fooAlias.id in (select e.id from foobar_table e, values_table v" +
" where e.id = v.entity_id and v.field = ?)", "abc123"), Hibernate.String)) ;
The solution with the sqlRestriction from jira
http://opensource.atlassian.com/projects/hibernate/browse/HHH-869
seemed the best way to go for me since i heavily use criteria api. I had to edit Thierry's code so it worked in my case
Model:
#Entity
public class PlatformData
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long iID;
private List<String> iPlatformAbilities = new ArrayList<String>();
}
Criteria call:
tCriteria.add(Restrictions.sqlRestriction(
"{alias}.id in (select e.id from platformData e, platformdata_platformabilities v"
+ " where e.id = v.platformdata_id and v.element = ? )", aPlatformAbility.toString(),
Hibernate.STRING));
For starters, I don't think Hibernate can map a List<String>. However, it can map a list of other entities.
So if your code was something like this:
#Entity
public class Foobar {
private List<EntityObject> uuids;
...
}
And the EntityObject has a String-property called str, the criteria could look like this:
List<Foobar> returns = (List<Foobar>) session
.createCriteria.(Foobar.class, "foobars")
.createAlias("foobars.uuids", "uuids")
.add(Restrictions.like("uuids.str", "%abc123%"))
.list();

Categories

Resources