I have these entities:
#Entity
#Table(name = "my_table")
public class MyTable implements Serializable {
#Id
#Column(name = "RECORD_ID")
private Long recordId;
#Column(name = "CNAME")
private String changeName;
#Transient
MyTableTwo tableTwo;
//getters and setters
}
MyTableTwo entity:
#Entity
#Table(name = "my_table_two")
public class MyTableTwo implements Serializable {
#Id
#Column(name = "REC_ID")
private Long recId;
#Column(name = "CNAME")
private String changeName;
#Column(name = "CVAL")
private String changeValue;
//getters and setters
}
I want to get my_table.record_id. 'my_table.cname', 'my_table_two.cval' in a result.
How to write a query on these two entities?
Can we write a join query with first entity and #transient entity field of 2nd entity?
I need to write HQL
You can do a cross join like
select a,b from MyTable a,MyTableTwo b where a.prop1 = b.prop2
Related
I need to concat some columns from both parent and child table using #Formula
Here is the Entities
#Entity
#Table(name = "parent1")
public class Parent1 implements Serializable {
#Id
private BigInteger id;
#Column(name = "childId")
private BigInteger childId;
#Column(name = "col1")
private String col1;
#Column(name = "col2")
private String col2;
#Formula("CONCAT_WS(' ',Parent2.child_colm,col1,col2)")
private String combinedName;
#OneToOne
#JoinColumn(name = "childId")
private Parent2 parent2;
}
#Entity
#Table(name = "parent2")
public class Parent2 implements Serializable {
#Id
#Column(name = "childId")
private BigInteger childId;
#Column(name = "child_colm")
private String child_colm;
}
While giving like this it returns Unknown column 'Parent2.child_colm'
I would suggest you instead of using #Formula here just write the following method:
import javax.persistence.Transient;
#Entity
#Table(name = "parent1")
public class Parent1 implements Serializable {
#Transient
public String getCombinedName() {
return Stream.of(parent2.child_colm, col1, col2)
.filter(s -> s != null && !s.isEmpty())
.collect(Collectors.joining(" "));
}
}
The #Transient annotation is used to specify that a given entity attribute should not be persisted.
I am looking to create a DAO which represents a join of two tables with Java Hibernate. Here is the SQL I'd like to represent (Postgres 9.6 incase that matters):
SELECT tableOneValue, tableTwoValue
FROM table_one, table_two
WHERE table_one_filter = 2 AND table_one_id = table_two_id;
These tables have a OneToOne relationship.
Table1.java
#Entity
#Data
#Table(name="table_one")
public class TableOneDao implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "table_one_id")
private int tableOneId;
#Column(name = "table_one_value")
private String tableOneValue;
#Column(name = "table_one_filter")
private int tableOneFilter;
}
Table2.java
#Entity
#Data
#Table(name="table_two")
public class TableTwoDao implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "table_twp_id")
private int tableTwpId;
#Column(name = "table_two_value")
private String tableTwoValue;
}
I'm very new to hibernate so maybe this isn't the right way to think with it. What I would love to do is define a SomeDao class where I can do: daoManager.findAll(SomeDao.class, Pair.of("tableOneFilter", 2));
This would return a List<SomeDao> where we get all the rows that satisfy tableOneFilter == 2.
You need to use the #OneToOne and #JoinColumn annotation.
Pay special attention to the userDetail attribute mapping.
For example, the user class:
#Entity
#Table(name = "USERS")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "USR_ID")
private long id;
#Column(name = "USERNAME", nullable = false, unique = true)
private String username;
#Column(name = "PASSWORD")
private String password;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="USR_DET_ID")
private UserDetail userDetail;
// Add Constructor, Setter and Getter methods
}
And this user details class:
#Entity
#Table(name = "USER_DETAILS")
public class UserDetail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "USR_DET_ID")
private long id;
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
#Column(name = "EMAIL")
private String email;
#Column(name = "DBO")
private LocalDate dob;
// Add Constructor, Setter and Getter methods
}
Check the full code here.
Here is a JPA query which will work with your existing entity structure with the latest version of hibernate.
SELECT t1.tableOneValue, t2.tableTwoValue
FROM TableOneDao AS t1 JOIN TableTwoDao AS t2 ON t1.table_one_id = t2.table_two_id
WHERE t1.table_one_filter = ?
You can write a JPQL statement which is much better. Here is the sample solution:
SELECT NEW com.test.package.dao(t1.valueOne, t2.valueTwo)
FROM table_one t1 JOIN table_two t2
WHERE t1.filter = 2 AND t1.id = t2.id;
Please refer to this link and jump to the section where it mentions Result Classes (Constructor Expressions). Hope it helps. Thanks.
I'm trying to build a multi-language database, so I've used this database design as a approach for mine.
Now I've two problems/questions:
I want to retrieve all LocalizedEvent for a given language and given categoryId. How can I make a inner join over the LocalizedCategory table with Hibernate Criteria API?
With SQL I would make this statement to get all LocalizedEvent + LocalizedCategory:
SELECT * FROM event e
INNER JOIN
localized_event le ON (le.event_id = e.event_id)
INNER JOIN
localized_category lc ON (lc.category_id = e.category_id)
WHERE
le.locale = 'de' AND lc.locale = 'de'
My current approach looks like this without getting the LocalizedCategory (with Criteria API):
Criteria c = session.createCriteria(LocalizedEvent.class, "localizedEvent");
c.createAlias("localizedEvent.event", "event");
c.createAlias("event.category", "category");
c.add(Restrictions.eq("category.categoryId", categoryId));
c.add(Restrictions.eq("localizedEvent.locale", language));
I think my mapping is not 100% correct. The entity LocalizedEvent should have a property localizedCategory, but I don't want to save the ID of this localizedCategory (therefore I'm using the #Transient annotation) in the LocalizedEvent table, e.g. using a ManyToOne relation (joining LOC_CATEGORY_ID). But I think it's not possible to do this, isn't it? I would have to map this transient field to LocalizedEvent "manually", because Hibernate is not supporting this mapping (if I'm right).
(Using JDBC this property/mapping would cause no problems, because I can easily make my inner joins and assign the property localizedCategory to the LocalizedEvent in a RowMapper or so).
My entities looks like this:
Event
#Entity
#Table(name = "EVENT")
public class Event {
#Id
#GeneratedValue
#Column(name = "EVENT_ID", unique = true)
private Long eventId;
#Column(name = "DATE")
private Date date;
#OneToMany(mappedBy = "event")
private Set<LocalizedEvent> localizedEvents;
#ManyToOne
#JoinColumn(name = "CATEGORY_ID")
private Category category;
}
LocalizedEvent
#Entity
#Table(name = "LOCALIZED_EVENT")
public class LocalizedEvent {
#Id
#GeneratedValue
#Column(name = "LOC_EVENT_ID")
private Long locEventId;
#ManyToOne
#JoinColumn(name = "EVENT_ID")
private Event event;
#Transient
private LocalizedCategory localizedCategory;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "LOCALE")
private String locale;
}
Category
#Entity
#Table(name = "CATEGORY")
public class Category {
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID", unique = true)
private Long categoryId;
#OneToMany(mappedBy = "category")
private Set<LocalizedCategory> localizedCategories;
#OneToMany(mappedBy = "category")
private Set<Event> events;
}
LocalizedCategory
#Entity
#Table(name = "LOCALIZED_CATEGORY")
public class LocalizedCategory {
#Id
#GeneratedValue
#Column(name = "LOC_CATEGORY_ID")
private Long locCategoryId;
#ManyToOne
#JoinColumn(name = "CATEGORY_ID")
private Category category;
#Column(name = "NAME")
private String name;
#Column(name = "LOCALE")
private String locale;
}
I have this UML diagram.
And I tried to build entities like this (I renamed Entity class to Entidad)
RelationshipType.java
#Entity
#Table(name = "relationship_type")
public class RelationshipType {
#Id
#GeneratedValue
private Long id;
private String type;
#OneToMany(mappedBy = "relationshipType", fetch = FetchType.EAGER)
private Set<Relationship> relationships = new HashSet<Relationship>();
//Getters and Setters
Relationship.java
#Entity
#Table(name = "relationship")
public class Relationship {
#Id
#ManyToOne
private RelationshipType relationshipType;
#Id
#ManyToOne
private Entidad entity;
//Getters and Setters
Entidad.java
#Entity
#Table(name = "entity")
public class Entidad {
#Id
#GeneratedValue
private Long id;
private String image;
private String foundationNotes;
private String alias;
private Boolean excludeNotifications;
private String notes;
//[...]
#ManyToOne
private Relationship related;
#OneToMany(mappedBy = "entity", fetch = FetchType.EAGER)
private Set<Relationship> relationships = new HashSet<Relationship>();
But when I launch app throws this:
Foreign key (FK_9d8afoh1pv9r59iwjkbcpnud1:entity [])) must have same number of columns as the referenced primary key (relationship [relationshipType_id,entity_id])
At now, I don't know where is the problem and need do this well because I'm using this entities to build the DB schema.
I need to create a table EMPLOYEE_REMARK from a table EMPLOYEE.
And need to do it with Annotation Hibernate.
EMPLOYEE
EMP_ID, EMP_FNAME, EMP_LNAME
EMPLOYEE_REMARK
EMP_REMARK_ID, EMP_ID, REMARK
it will be a OnetoOne relationship i.e, for each EMP_ID there will be one REMARK. REMARK could be null.
please help me with the solution...
Can it be done by creating one class from employee and populate the EMPLOYEE_REMARK from it???
Basically here is the way of doing what you want.
Employee
#Entity
#Table(name = "EMPLOYEE")
public class Employee implements Serializable {
#Id
#Column(name = "EMP_ID")
private Long id;
#Column(name = "EMP_FNAME")
private String firstName;
#Column(name = "EMP_LNAME")
private String lastName;
#OneToOne(mappedBy = "employee", cascade = CascadeType.ALL,
orphanRemoval = true)
private EmployeeRemark employeeRemark;
public void setRemark(String remark) {
this.employeeRemark = new EmployeeRemark();
this.employeeRemark.setRemark(remark);
this.employeeRemark.setEmployee(this);
}
public String getRemark() {
return employeeRemark == null ? null : employeeRemark.getRemark();
}
//getters and setters
}
Employee Remark
#Entity
#Table(name = "EMPLOYEE_REMARK")
public class EmployeeRemark implements Serializable {
#Id
#Column(name = "EMP_REMARK_ID")
private Long id;
#OneToOne
#JoinColumn(name = "EMP_ID")
private Employee employee;
#Column(name = "REMARK")
private String remark;
//getters and setters
}
When saving employee, just call save on employee. EmployeeRemark will cascade to all operations and will be removed along with employee or if it become an orphan in other way.