Multiple Joins with Hibernate but with different columns - java

I need to recreate this query:
select distinct
limits.domains_limit,
limits.emails_limit,
limits.keywords_limit
from user_schema.tenant_limits as limits
join user_schema.tenant as tenants on limits.tenant_id = tenants.id
join profile_schema.profile as profiles on tenants."name" = 'test'
The relevant part of the tables I have to go through are:
PROFILE(Table)
- Tenant (refer to TENANTS.name)
TENANTS (Table)
- id
- name
LIMITS (Table)
- tenant_id (refer to TENANTS.id)
And what I basically need to do is given a Profile (which contains a tenant name) I need to fetch the limits for the tenant. How can I set it up with Hibernate Annotations?
Profile.java
public class Profile {
// other properties ...
#Column(name = "tenant", nullable = false, updatable = false)
private String tenant;
//How to fetch limits here?
private ProfileLimits limits;
}
TenantsLimit
public class ProfileLimits {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long tenant_id;
#Column(name = "domains_limit", nullable = true, updatable = true)
private Long domains;
#Column(name = "emails_limit", nullable = true, updatable = true)
private Long emails;
#Column(name = "keywords_limit", nullable = true, updatable = true)
private Long keywords;
}

Related

Hibernate Envers: Query deleted Entity by value of foreign key column

Hi hibernate (envers) experts!
I currently have two/three entities
Automations which represent an automated process for one answer of a question (of a survey)
Answers answer of a user for a question (of a survey)
BaseEntity which is extended by Automations and Answers an has basic attributes like modify timestamps and so on.
The Automations table is audited by hibernate envers.
I want to fetch all deleted Automations for one specific Answer. The generated and executed query from hibernate does include my condition for the "deleted" revtype of envers but not my condition for the answer.
See the function listHistoryByAnswer
#MappedSuperclass
public class BaseEntity extends PanacheEntityBase {
#Id
#Column(name = "UUID", updatable = false, nullable = false, columnDefinition = "uuid")
private UUID _uuid;
#Column(name = "CREATED_AT", nullable = false, updatable = false, columnDefinition = "TIMESTAMP without time zone")
#CreationTimestamp
private Timestamp createdAt;
#Column(name = "CREATED_BY", nullable = false, updatable = false)
private String createdBy;
#Column(name = "UPDATED_AT", columnDefinition = "TIMESTAMP without time zone")
#UpdateTimestamp
private Timestamp updatedAt;
#Column(name = "UPDATED_BY")
private String updatedBy;
}
#Entity
#Table(name = "AUTOMATION", uniqueConstraints = #UniqueConstraint(columnNames = {"ANSWER_UUID"}))
#Audited
public class Automation extends BaseEntity {
#Basic
#Column(name = "DESCRIPTION")
private String description;
#JsonBackReference("automation-answer")
#ManyToOne
#JoinColumn(name = "ANSWER_UUID", nullable = false)
private Answer answer;
}
#Entity
#Table(name = "ANSWER")
#Audited(targetAuditMode = NOT_AUDITED)
public class Answer extends BaseEntity {
#JsonManagedReference("automation-answer")
#OneToMany(mappedBy = "answer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Automation> automations = new ArrayList<>();
#Column(name = "DATA", columnDefinition = "jsonb")
private JsonNode data;
}
/**
* List old (deleted) questions based on the answer
* #param answerUuid unique id of the answer
* #return list with deleted questions
*/
public List<Automation> listHistoryByAnswer(final UUID answerUuid){
List resultList = AuditReaderFactory.get(getEntityManager())
.createQuery()
.forRevisionsOfEntity(Automation.class, true)
.add(AuditEntity.revisionType().eq(RevisionType.DEL))
.add(AuditEntity.property("answer_uuid").eq(answerUuid))
.getResultList();
return resultList;
}
Generated SQL
select automation0_.UUID as uuid1_1_0_,
automation0_.REV as rev2_1_0_,
defaultrev1_.REV as rev1_15_1_,
automation0_.REVTYPE as revtype3_1_0_,
automation0_.ANSWER_UUID as answer_u9_1_0_,
defaultrev1_.REVTSTMP as revtstmp2_15_1_
from A_AUTOMATION_HIS automation0_
cross join
REVINFO defaultrev1_
where automation0_.REVTYPE = 2 -- DELETED entities
and automation0_.REV = defaultrev1_.REV
order by automation0_.REV asc;

How to write string date value in import.sql file so that Hibernate can create and insert into MySQL?

I have simple class:
#Entity
#Table(name = "task")
public class Task {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private int id;
#Column(name = "date_time", unique = false, nullable = false)
private LocalDateTime date_time;
}
In my import.sql file, I have following:
INSERT INTO todo_project.task ( active, date_time, title, done) VALUES ( true, 'some-string-for-date-time', 'do homework', false);
What to set for some-string-for-date-time?

Entity not using specified sequence while saving in JPA for postgres

I want to use custom sequence(orderId_seq) while saving my entity instead of default one(hibernate_sequence) in postgres-9.5.
My entity is :
#Entity
#Table(name="orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "orderId_generator")
#SequenceGenerator(name="orderId_generator", sequenceName = "orderId_seq")
#Column(updatable = false, nullable = false)
private Long orderId;
#Column(columnDefinition = "uuid",nullable = false)
#Type(type="pg-uuid")
private UUID userId;
private String comments;
private String assignedTo;
#Enumerated(EnumType.STRING)
#Column(nullable = false)
private OrderStatus status;
#Column(nullable = false, updatable = false, insertable = false,
columnDefinition = "TIMESTAMP with time zone DEFAULT CURRENT_TIMESTAMP")
private Timestamp orderedDate;
//getters and setters
when I save this entity to the database. It is generating some random number for orderId instead of using orderId_seq.
When I check the order entity in debug mode before saving it is null but after saving it is creating some random number not even using hibernate_sequence.
And when I use show_sql=true option in hibernate it is even showing the following statement in the console :
Hibernate:
select
nextval ('orderId_seq')
How can I resolve this issue?

How to fetch data from multiple table query by hibernate?

I have a user management application that allocate each user a team and one or many access to different application. Now for the reporting page I am trying to fetch data from two table (UserInfo & UserAppAccess) by Hibernate but I can't.
Here are the tables :
Table 1 (UserInfo):
#Entity
#Table(name = "user_info", uniqueConstraints = { #UniqueConstraint(columnNames = "username"), #UniqueConstraint(columnNames = "email") })
public class UserInfo implements java.io.Serializable {
public enum UserStatus {
active, inactive
}
public enum UserType {
user, creator
}
private static final long serialVersionUID = 2650114334774359089L;
#Id
#Column(name = "id", unique = true, nullable = false, length = 100)
private String id;
#Column(name = "username", unique = true, nullable = false, length = 50)
private String username;
#Column(name = "password", nullable = false, length = 80)
private String password;
#Column(name = "status", nullable = false, length = 10)
#Enumerated(EnumType.STRING)
private UserStatus status;
#Column(name = "type", nullable = false, length = 10)
#Enumerated(EnumType.STRING)
private UserType type;
#Column(name = "phone", nullable = true, length = 30)
private String phone;
#Column(name = "email", nullable = true, length = 50)
private String email;
#Column(name = "first_name", nullable = true, length = 50)
private String firstName;
#Column(name = "last_name", nullable = true, length = 50)
private String lastName;
#Column(name = "login", nullable = true, length = 100)
private long login;
#Column(name = "alert", nullable= true, length=500)
private String alert;
#OneToOne
#JoinColumn(name = "team_id")
private Team team;
}
Table 2 (Team):
#Entity
#Table(name = "team", uniqueConstraints = { #UniqueConstraint(columnNames = "team_name"), #UniqueConstraint(columnNames = "team_code") })
public class Team implements java.io.Serializable {
private static final long serialVersionUID = 7933770163144650730L;
#Id
#Column(name = "id", unique = true, nullable = false, length = 80)
private String id;
#Column(name = "team_name", unique = true, nullable = false, length = 100)
private String name;
#Column(name = "team_code", unique = true, nullable = false, length = 10)
private String code;
}
Table 3 (Access):
#Entity
#Table(name = "access_def")
public class Access implements java.io.Serializable {
private static final long serialVersionUID = 7933770163144650730L;
#Id
#Column(name = "id", unique = true, nullable = false, length = 80)
private String id;
#Column(name = "access_name", unique = true, nullable = false, length = 100)
private String name;
#Column(name = "access_code", unique = true, nullable = false, length = 10)
private String code;
}
Table 4 (Application):
#Entity
#Table(name = "application", uniqueConstraints = { #UniqueConstraint(columnNames = "name") })
public class Application implements java.io.Serializable {
private static final long serialVersionUID = 5803631085624275364L;
#Id
#Column(name = "name", nullable = false, length = 100)
private String name;
}
Table 5 (UserAppAccess):
#Entity
#Table(name = "user_app_access")
#Embeddable
public class UserAppAccess implements java.io.Serializable {
private static final long serialVersionUID = 7933770163144650730L;
#Id
#Column(name = "id", unique = true, nullable = false, length = 80)
private String id;
#OneToOne
#JoinColumn(name = "user_id")
private UserInfo userInfo;
#Column(name = "app_name", nullable = false, length = 100)
private String appName;
#OneToOne
#JoinColumn(name = "access_id")
private Access access;
}
I have a report page that allow Admin to select multiple options (for example: list all active users in Team test and application APP1).
here is my code to fetch the data but it is not working :
public List<?> getReport(String teamId,String appName,UserStatus active,UserStatus inactive) {
Session session = sessionFactory.getCurrentSession();
String hql = "SELECT u.firstName,u.username,u.status,u.lastName,u.phone,u.team From UserInfo u,AppAccess a WHERE u.status =? OR u.status =? AND u.team.id = ? AND a.appName = :appName ";
Query query = session.createQuery(hql);
query.setParameter(0, active);
query.setParameter(1, inactive);
query.setParameter(2, teamId);
query.setParameter("appName", appName);
System.out.println(query.list());
return query.list();
}
For instance when I pass
Active Users: Active
inactive User:null
team:test
application :app1
teamId :28f66133-26c3-442b-a071-4d19d64ec0aeappName :app1active :activeinactive:null
I am getting this back from my return query.list();
[[Ljava.lang.Object;#2961116f, [Ljava.lang.Object;#23bfa3a2, [Ljava.lang.Object;#7a8ff303, [Ljava.lang.Object;#9b88d2, [Ljava.lang.Object;#6333934d, [Ljava.lang.Object;#4f0bd71c, [Ljava.lang.Object;#125797cf, [Ljava.lang.Object;#34afa071, [Ljava.lang.Object;#764e75bc, [Ljava.lang.Object;#1913c652, [Ljava.lang.Object;#61413e5a, [Ljava.lang.Object;#264b898, [Ljava.lang.Object;#22930462, [Ljava.lang.Object;#6204cfa9, [Ljava.lang.Object;#29dd9285, [Ljava.lang.Object;#11be6f3c, [Ljava.lang.Object;#6d78d53d, [Ljava.lang.Object;#17f7cff1, [Ljava.lang.Object;#e74e382, [Ljava.lang.Object;#1c047338, [Ljava.lang.Object;#68286fe6, [Ljava.lang.Object;#36ca9a76, [Ljava.lang.Object;#2f62d514, [Ljava.lang.Object;#1932c5a, [Ljava.lang.Object;#6544c984, [Ljava.lang.Object;#70a2d0d, [Ljava.lang.Object;#2d13b417, [Ljava.lang.Object;#6894691f, [Ljava.lang.Object;#6781a7dc, [Ljava.lang.Object;#7133919a]
I'd suggest using native SQL and JDBC for reporting (see
How should I use Hibernate Mapping while dealing with huge data table)
For performance reasons it is desirable to create view model objects from result set right in the DAO. It may looks like mixing levels of abstraction (view layer with persistence layer), but it's ok when you need to fetch a big amounts of data and don't want to make unnecessary object transformations from persistence models to view models.
If you're want to stuck with hibernate, you may define a syntetic entity and map if on a view, containing only necessary columns from multiple:
#Entity
#Table("V_USER_REPORT")
public class UserAppData {
// columns from table "user"
#Id
#Column(name = "id", unique = true, nullable = false, length = 100)
private String id;
#Column(name = "username", unique = true, nullable = false, length = 50)
private String username;
// columns from table "user"
#Column(name = "app_name", nullable = false, length = 100)
private String appName;
// columns from table "team"
#Column(name = "team_id", unique = true, nullable = false, length = 80)
private String team_id;
#Column(name = "team_name", unique = true, nullable = false, length = 100)
private String name;
#Column(name = "team_code", unique = true, nullable = false, length = 10)
private String code;
// and so on...
}
Then you fetch such entity by parameters as you do it with normal entity.
By adding LEFT JOIN FETCH or FETCH ALL PROPERTIES. This will force JOINS insteed of lazy initialization
String hql = "SELECT u.firstName,u.username,u.status,u.lastName,u.phone,u.team From UserInfo u,AppAccess a FETCH ALL PROPERTIES WHERE u.status =? OR u.status =? AND u.team.id = ? AND a.appName = :appName ";
More information can be found in HQL Documentation
Firstly: I hope each of your entity classes have a toString() method (can be auto-generated with eclipse) so you can print them. Printing object reference isn't enough to infer whether/not you're getting what you want.
Secondly, the syntax of HQL joins is normally like this:
String queryString = "select distinct f from Foo f inner join foo.bars as b" +
" where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
(taken from How do you create a Distinct query in HQL)

Which data format is suitable to transfer data (result of left join db query) from servlet to JSP?

[using JPA, MySQL, MVC, Servlets, JSP]
If I read some data from database LEFT JOIN-ing three tables (inside method of DAO object) how should I format that result, so i can set it as request attribute (in servlet) and forwards to JSP page?
Entities(tables in db):
Post:
#Entity
#Table(name = "post")
public class Post implements Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "post_id", unique = true, nullable = false)
private Integer id;
#Column(name = "post_title", length=300, unique = false, nullable = false)
private String title;
#Column(name = "post_date", unique = false, nullable = false)
private Date date;
#Column(name = "post_summary", length=1000, unique = false, nullable = true)
private String summary;
#Column(name = "post_content", length=50000, unique = false, nullable = false)
private String content;
#Column(name = "post_visitors", unique = false, nullable = false)
private Integer visitors;
#ManyToOne
#JoinColumn (name = "user_id", referencedColumnName="user_id", nullable = false)
private User user;
#ManyToOne
#JoinColumn (name = "category_id", referencedColumnName="category_id", nullable = false)
private Category category;
#OneToMany(cascade = { ALL }, fetch = LAZY, mappedBy = "post")
private Set<Comment> comments = new HashSet<Comment>();
...
Entity Comment:
#Entity
#Table(name = "comment")
public class Comment implements Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "comment_id", unique = true, nullable = false)
private Integer id;
#Column(name = "comment_title", length=300, unique = false, nullable = false)
private String title;
#Column(name = "comment_date", unique = false, nullable = false)
private Date date;
#Column(name = "comment_content", length=600, unique = false, nullable = false)
private String content;
#ManyToOne
#JoinColumn (name = "user_id", referencedColumnName="user_id", nullable = false)
private User user;
#ManyToOne
#JoinColumn (name = "post_id", referencedColumnName="post_id", nullable = false)
private Post post;
...
Entity User:
#Entity
#Table(name = "user")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_id", unique = true, nullable = false)
private Integer id;
#Column(name = "user_name", length=45, unique = false, nullable = false)
private String name; // "first_name" + ' ' + "last_name"
//URL address to user's image
#Column(name = "user_image", length=500, unique = false, nullable = true)
private String image;
#Column(name = "user_username", length=45, unique = false, nullable = false)
private String username;
#Column(name = "user_password", length=45, unique = false, nullable = false)
private String password;
...
So, I would like to make a method, probably inside PostDAO object that will look something like this:
public <SomeDataTypeFormat???> getPostsSummaries(){
Query q = em.createNativeQuery("SELECT
post_title,
post_summary,
post_date,
COUNT(comment_id) AS comment_cnt,
user.user_name
FROM
post
LEFT JOIN user USING(user_id)
LEFT JOIN comment USING(post_id)
GROUP BY
post_id
ORDER BY
comment_cnt DESC");
...
}
Method returns some fields from all three tables in database.
Do I need to make separate class and store those data in objects of that class? Or JSON (although I haven't worked with it yet)?
What is the practice? What is easiest data format to use and forward from servlet to JSP, for some fields gotten as a result of joining couple tables?
It depends on your objective; to get the data to the browser, JSON and AJAX isn't a bad choice. To get the data to the JSP (from the Servlet), you'll probably want a Data Transfer Object (or possibly an immutable Value Object).

Categories

Resources