JPA Index specification on substring - java

I'd like to define such an index: create index annuaire_abc_substr_idx on annuaire(substring(abc,7,2));
Whith JPA Specification I'd like to write something like this:
#Entity
#Table(name = "annuaire",
indexes = {
#Index(name = "annuaire_abc_substr_idx", columnList = "???")
}
)
Is there a way to use this javax.persistence.Index annotation to work with a substring?

Related

How to get collection of property in Join JPA criteria API

I'm trying to get a list of property policy_type_id from ListAttribute<Article, PolicyType>, but I can't figure out how to do it.
I come up with an inefficient method was select whole Collection of PolicyType then filter it later
Root<ArticleVersion> a = cq.from(ArticleVersion.class);
Join<ArticleVersion, Article> join1 = a.join(ArticleVersion_.article, JoinType.INNER);
cq.where(getCondition(cb, join1));
cq.multiselect(join1.get(Article_.article_id), join1.get(Article_.policyTypes), a);
Sadly, hibernate generate an error query like this
select article1_.article_id as col_0_0_, . as col_1_0_, articlever0_.article_version_id as col_2_0_ . As you can see, there is a . in select that make query broken (which I believe select all)
#Entity
#Table(name = "PolicyType", schema = "SM_Request")
#Getter
#Setter
#NoArgsConstructor
public class PolicyType {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int policy_type_id;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "PolicyTypeArticle", schema = "SM_Request",
joinColumns = #JoinColumn(name = "policy_type_id"), inverseJoinColumns = #JoinColumn(name = "article_id"))
#JsonIgnore
private List<Article> articles;
}
After long searching, I think that hibernate doesn't support query tuple of primitive types and list of objects (which is kinda sad, compare to LINQ to query). I decided to break down my query into smaller parts. First, I select tuples of article_id and ArticleVersion. After that, I select a list of PolicyType which also contains article_id, and union 2 lists back.
By the time I wrote this, I have an idea that I could select all 3 joins together and transform data the way I want. But It really depend on many aspects, like how many join or which type of join you're using, how fast data in each table grown (JOIN queries vs multiple queries)

Pulling a field from another table in Hibernate

I have two tables, which have a one-to-one relationship and look something like this:
OrderItem
ID data1 data2 data3
1 a b c
2 d e f
3 g h i
DisputedItem
ID data4
1 q
3 r
Is there a way to pull data4 into my Hibernate model for OrderItem without having a separate DisputedItemModel? Preferably using annotations.
You can use Hibernate #Formula annotation, if you have annotation based mappings or <formula> tag if you are mapping by XML.
What formula can do is help you extract a value by a query and map it to a field in your OrderItem domain model. This field can be from any table but the query thats used to map the property should return the indented field type.
You can use following URL for reference Hibernate Formula
Yes, here is an example:
#Table(name = "table")
public class c
{
#Id
#Column(name = "ID")
private int Id;
#Formula("(select t.data from table t where t.ID = ID))")
private String data;
}

HQL. Intersection of two lists

Update: look my answer below on how to check if 2 list intersects (both for #ElementCollection with string/enums and usual entities list mapped like #OneToMany)
I have an entity which contains #ElementCollectionfield with enums.
public enum StatusType {
NEW, PENDING, CLOSED;
}
#Entity
public class MyEntity {
#ElementCollection
#CollectionTable(name = "status_type", joinColumns = {#JoinColumn(name = "my_entity_id")})
#Column(name = "status_type", nullable = false)
private Set<StatusType > statusTypes = new HashSet<StatusType >();
...
}
Now I want to get all entities which contains status NEW or PENDING (or both).
I'm trying to use this query:
SELECT DISTINCT u FROM MyEntity u WHERE u.statusTypes in :statusTypes
But I'm getting exception: org.postgresql.util.PSQLException: No value specified for parameter 9.
How to properly query on collections and filter by intersections?
Problem solved by adding JOIN clause to HQL. Hibernate couldn't implicitly recognize that query needs JOIN clause. May be it will help someone:
SELECT DISTINCT u FROM MyEntity u
LEFT JOIN u.statusTypes statusTypes
WHERE statusTypes in :statusTypes
I set the query params like this:
query.setParameter( "statusTypes", listOfStatusTypesEnums);
It will select rows where at least one element of listOfStatusTypesEnums list is present in entity's statusTypes property (i.e. if 2 list are intersects in some way).
If you have usual list of entities (which are not #ElementCollection, but #OneToMany etc), same rule will work as well. Just use like this: LEFT JOIN u.subEntities subEntities WHERE subEntities.id in :subEntityIds

Named entity graph JOINS results (need distinct option) in Spring Data JPA

I'm using #NamedEntityGraph annotation to load a graph from database.
#NamedEntityGraph(
name = "Firma.uredjivanje",
attributeNodes = {
#NamedAttributeNode(value="prevodi", subgraph = "prevodi")
},
subgraphs = {
#NamedSubgraph(
name = "prevodi",
attributeNodes = {
#NamedAttributeNode(value = "jezik", subgraph = "jezik")
}
)
}
)
In the Spring Data JPA repository, I'm using annotation:
#EntityGraph(value="Firma.uredjivanje", type = EntityGraph.EntityGraphType.LOAD)
List<Firma> getByAktivna(boolean aktivna);
Everything works as expected, expect that all relations are joined, and I get duplicate Firma entities (because of JOIN). Instead of a List with entity id's {1,2,3}, I get {1,1,1,2,2,3}.
What is the best way to get distinct entities (if this is not a bug ofcourse).
Found the answer... Since NamedEntityGraph does JOIN in database, it selects all entities without DISTINCT. So the solution is to use Distinct in method name...
#EntityGraph(value="Firma.uredjivanje", type = EntityGraph.EntityGraphType.LOAD)
List<Firma> getDistinctByAktivna(boolean aktivna);
After adding dictinct I have error logs during server starup (maybe because there is no such thing as findDistinctAll() .
For me help a hint in https://jira.spring.io/browse/DATAJPA-680.
I added #Query annotation to the method, so my method looks like below
#EntityGraph(value = "User.detail", type = EntityGraph.EntityGraphType.LOAD)
#Query(value = "SELECT DISTINCT u FROM User u")
List<User> findAll();

Hibernate entity with restriction

We have a DB table that is mapped into a hibernate entity. So far everything goes well...
However what we want is to only map enentitys that satisty a specific criteria, like ' distinct(fieldA,fieldB) '...
Is it possible to map with hibernate and hibernate annotations? How can we do it? With #Filter?
I would recommend that you use #Where annotation. This annotation can be used on the element Entity or target entity of a collection. You provide a clause attribute written in sql that will be applied to any select that hibernate performs on that entity. It is very easy to use and very readable.
Here is an example.
#Entity
//I am only interested in Donuts that have NOT been eaten
#Where(clause = "EATEN_YN = 'N'")
public class Donut {
#Column(name = "FILLING")
private String filling;
#Column(name = "GLAZED")
private boolean glazed = true;
#Column(name = "EATEN_YN")
private boolean eaten = false;
...
}
You could create a view and then map that view to entity:
create view my_data as
select ... from ...
#Entity(table="my_data")
public class MyData { ... }
One option is to map the table normally, then you could fetch your always entities through a query or a filter.
You could also make a native SQL query and map the entity on the results:
Query q = sess.createSQLQuery("SELECT DISTINCT fieldA, fieldB FROM some_table")
.addEntity(MyEntity.class);
List<MyEntity> cats = q.list();
It might be also possible to add DISTINCT to this type of HQL query:
select new Family(mother, mate, offspr)
from DomesticCat as mother
join mother.mate as mate
left join mother.kittens as offspr
Methods 1, 3 and 4 will make a read-only mapping.
Could you be more specific about the criteria you are using? The view approach is more generic since you can't do everything with a hibernate query or filter.
perhaps you could create a new Pojo that encapsulates the fields and the condition that they should statisy . And then then make that class a 'custom user defined type', such that Hibernate will have to use the mapping class that you provide, for mapping that 'type'..
In addition to the options mentioned by Juha, you can also create an object directly out of a SQL query using the NamedNativeQuery and SqlResultSetMapping annotations.
#Entity
#SqlResultSetMapping(name = "compositekey", entities =
#EntityResult(entityClass = MiniBar.class,
fields = { #FieldResult(name = "miniBar", column = "BAR_ID"), })
)
#NamedNativeQuery(name = "compositekey",
query = "select BAR_ID from BAR", resultSetMapping = "compositekey")
#Table(name = "BAR")
public class Bar {
Flavor the SQL query to your taste

Categories