I have next classes:
#Entity
#Table(name="A")
public class A implements Serializable{
#Id
#Column(name="a_id")
private long aId;
#ManyToOne
#JoinColumn(name="b_id")
private B b;
}
#Entity
#Table(name="b")
public class B implements Serializable{
#Id
#Column(name="b_id")
private long bId;
#Column(name="b_name")
private String name;
#Column(name="b_age")
private String age;
#OneToMany(mappedBy="b")
private Set<A> a;
}
I have getters and setters for this classes.
when I try execute next Criteria
session.createCriteria(A.class, "a_table")
.createAlias("a_table.b", "b_table")
.add(Restrictions.eq("b_table.age", "11"))
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
In SQL generated by hibernate I have all fields from B (I mean field "name" too).
How I can make to Hibernate bring only needed fields.
In case that in criteria exists many aliases to many tables, it can increase execution time.
Thank you.
Try using projections. Maybe something like this:
Criteria cr = session.createCriteria(User.class)
.setProjection(Projections.projectionList()
.add(Projections.property("id"), "id")
.add(Projections.property("Name"), "Name"))
.setResultTransformer(Transformers.aliasToBean(User.class));
List list = cr.list();
Related
I am trying to use Hibernate Criteria api to fetch only the topics based on the USER_ID but have no idea how to do it using the criteria.
My Tables are "topic_users" (below)
and "topics" table (below)
I know how to do it using SQL, this would be something like:
SELECT TOPICNAME
FROM topic_users INNER JOIN topics on topic_users.TOPICS_TOPICS_ID = topics.TOPICS_ID
WHERE topic_users.USER_ID = 1
This will return all TOPICNAME of USER_ID 1 which is exactly what I want but how I can do this with Hibernate Criteria. So far I have this in my Repository class (see below) but this will only return a highly nested JSON array. I could loop through the objects, use a DTO and build my response or try the Hibernate createSQLQuery method that will let me call a native SQL statement directly (haven't tried that yet)...but I am trying to learn the Criteria so I hope anyone can answer my query.
#Repository("userTopicsDao")
public class UserTopicsDaoImpl extends AbstractDao<Integer, UserTopics>implements UserTopicsDao {
#Override
public List<UserTopics> findMyTopics(int userId) {
Criteria crit = createEntityCriteria();
crit.add(Restrictions.eq("userId", userId));
List<UserTopics> userTopicsList = (List<UserTopics>)crit.list();
return userTopicsList;
}
and my TOPIC_USERS Entity where I have mapped the TOPICS
#Entity
#Table(name="TOPIC_USERS")
public class UserTopics {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="TOPICUSER_ID")
private Integer id;
#Column(name="USER_ID")
private Integer userId;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "TOPICS_ID")
private Set<Topics> topicsUser;
//getter and setters
Ok starting from the ground up.. you entity classes should look like this:
#Entity
#Table(name="TOPIC_USERS")
public class UserTopics {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="TOPICUSER_ID")
private Integer id;
#Column(name="USER_ID")
private Integer userId;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "TOPICS_TOPICS_ID")
private Topics topics;
Your Topics class should look like this:
#Entity
#Table(name="TOPICS")
public class Topic {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="TOPICUS_ID")
private Integer id;
#Column(name="TOPICNAME")
private Integer topicName;
#OneToMany(mappedBy = "topics")
private Set<UserTopics> userTopics;
Finally the Criteria:
Version 1) You get entire entity:
Criteria c = session.createCriteria(Topics.class, "topics");
c.createAlias("topics.userTopics", "userTopics");
c.add(Restrictions.eq("userTopics.userId", userId));
return c.list(); // here you return List<Topics>
Version 2) You project only the topicname:
Criteria c = session.createCriteria(Topics.class, "topics");
c.createAlias("topics.userTopics", "userTopics");
c.add(Restrictions.eq("userTopics.userId", userId));
c.setProjection(Projections.property("topics.topicName"));
List<Object[]> results = (List<Object[]>)c.list();
// Here you have to manually get the topicname from Object[] table.
}
Assuming theses Entities
#Entity
public class EntityNote implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="SeqEntityNote", sequenceName="SeqEntityNote", allocationSize = 1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SeqEntityNote")
private long id;
private Date date;
private String subject;
private String content;
#ManyToMany
private List<EntityTopic> listEntityTopic;
//setters/getters
#Entity
public class EntityTopic implements Serializable {
#Id
#SequenceGenerator(name="SeqEntityTopic", sequenceName="SeqEntityTopic", allocationSize = 1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SeqEntityTopic")
private long id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
In my DB, a join table named "entity_note_list_entity_topic" records the ManyToMany relation.
This works correctly so far.
But I'd like to perform a count query like 'how many EntityNotes per EntitityTopic'
Unfortunatly I'm quite lost in this situation.
How this query can be written ?
Do I need other elements in my two entities ?
(In many examples I see a reverse relation using mappedBy attribute on ManyToMany.. Do I need this ?)
It will be the easiest if you make the many to many relation bidirectional. There are no serious extra costs involved, as it uses the same db structure, and the list are lazy loaded so if the relation is not being used the lists are not populated (you can hide the second direction by making accessors private).
Simply change:
#Entity
public class EntityTopic implements Serializable {
...
#ManyToMany(mappedBy="listEntityTopic")
private List<EntityNote> notes;
}
You can issue normal count jpql queries, for example:
SELECT count(n) from EntityTopic t INNER JOIN t.notes n where t.name =:name
so you don't neet to retrieve the notes and topics if don't need to.
But I also believe that your original mapping can also be queries with:
SELECT COUNT(n) FROM EntityNote n INNER JOIN n.listEntityTopic t WHERE t.name = :name
If you have the following code:
#Entity
public class EntityNote implements Serializable {
#ManyToMany(fetch = FetchType.LAZY)
private List<EntityTopic> topics;
}
#Entity
public class EntityTopic implements Serializable {
#ManyToMany(fetch = FetchType.LAZY)
private List<EntityNote> notes;
}
Then, topic.getNotes().size() will give you the number of notes associated with a topic. When using Hibernate as the JPA provider, a SELECT COUNT(...) query is issued for this instead of loading all the associated notes. If this does not work for you out-of-the-box, mark the collections as extra lazy using the instructions in this post.
I am using Sprind JPA, Spring 3.1.2(in future 3.2.3), Hibernate 4.1 final.
I am new to Sprind Data JPA. I have tow Table Release_date_type and Cache_media which entities are as follows :
ReleaseAirDate.java
#Entity
#Table(name = "Release_date_type")
public class ReleaseDateType {
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
private Integer release_date_type_id;
#Column
private Integer sort_order;
#Column
private String description;
#Column
private String data_source_type;
#Column(nullable = true)
private Integer media_Id;
#Column
private String source_system; with getters and setters..
and CacheMedia as
#Entity
#Table(name = "Cache_Media")
public class CacheMedia {
#Id
#GeneratedValue(strategy=GenerationType.TABLE)
private Integer id;
#Column(name="code")
private String code;
#Column(name="POSITION")
private Integer position;
#Column(name="DESCRIPTION")
private String media_Description; with setter and getters.
Now my repository interface is as follows :
public interface ReleaseDateTypeRepository extends CrudRepository<ReleaseDateType, Long>{ }
Now i want to write a method(Query) in ReleaseDateTypeRepository interface which can get all the data from Release_Date_Type table including appropriate media_description from Table 'Cache_Media' based on media_id of Release_date_type table.
So my select (SQL)query looks like
SELECT * from Release_Date_Type r left join Cache_Media c on r.media_id=c.id
I don't know how to map entities.
I tried so many thing but not luck.
Any help is appreciated.
Its not the answer for joining via Hibernate, but alternatively you can create a view with your join and map the view to your objects
I have two tables: Organization(Parent) and Department(Child).
There is One to Many relationship, and is mentioned in Organization table only.
#Entity
#Table(name="TBL_STD_ORGANIZATION")
public class Organization implements Serializable {
#Id
#GeneratedValue
#Column(name="FLD_ORG_ID")
private Long organizationId;
#Column(name="FLD_ORG_NAME")
private String orgName;
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private java.util.List<Department> listOfDepartMents = new java.util.ArrayList<Department>();
}
Below is Department Class:
#Entity
#Table(name="TBL_STD_DEPARTMENT")
public class Department implements Serializable {
#Id
#GeneratedValue
#Column(name = "FLD_DEPARTMENT_ID")
private Long departmentId;
#Column(name = "FLD_DEPARTMENT_NAME")
private String departmentName;
}
I wrote relationship in Parent table, because of it hibernate creates third table.
Now, I have to retrieve departments start with "sa" keyword and in specific organization.
So I want the HQL or SQL query query. I am not getting it how to write such complex query.
Any suggestions?
I'm fairly certain the HQL/JPQL would be:
SELECT d FROM Organization o JOIN o.listOfDepartMents d WHERE d.departmentName LIKE "sa%"
I'm trying to select entries for Entity A where all of the children in its collection of CReference entities meet a condition. The query I currently have only requires the conditions to be met on at least one of the members.
Current Query
This query currently selects all objects of type A where at least one of the items in its c_references class
SELECT a FROM A a INNER JOIN FETCH a.c_references c_refs INNER JOIN FETCH c_refs.c_reference c_ref WHERE (c_ref.flag_one=TRUE AND c_ref.flag_two=TRUE)
Classes
Class A
#Entity
public class A{
#Id
private UUID a_uuid;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "owning_a_uuid")
private List<CReference> c_references;
}
Class CReference
#Entity
// This class keeps references to all of the A objects that have referenced a C object
public class CReference{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long c_reference_id;
#OneToOne
private A a_referencing_c;
#OneToOne
private C c_reference;
}
Class C
#Entity
#Cacheable
public class C{
#Id
private UUID c_uuid;
private Boolean flag_one = false;
private Boolean flag_two = false;
}
Try this:
SELECT a FROM A a
WHERE NOT EXISTS(
SELECT c_refs
FROM CReference c_refs
INNER JOIN c.c_reference c_ref
WHERE
c_refs.a_referencing_c = a
AND (c_ref.flag_one = FALSE OR c_ref.flag_two = FALSE)
)