querydsl instance variables - jpa

From QueryDSL JPA Tutorial, I could not find differences between default instance variable generated by querydsl and custom variable.
For the entity Customer defined as
#Entity
public class Customer {
private String firstName;
private String lastName;
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
public void setFirstName(String fn){
firstName = fn;
}
public void setLastName(String ln)[
lastName = ln;
}
}
What is the difference between using default instance variable and custom as follows ?
QCustomer customer = QCustomer.customer;
VS
QCustomer customer = new QCustomer("myCustomer");
What could be the possible use cases for custom variable as in second one?

The variable name is used as such in the serialization. If you need to refer to multiple instances of the same type in your query, you need to use multiple variables.
Here is an example
QCustomer customer = QCustomer.customer;
QCustomer customer2 = new QCustomer("customer2");
List<Customer> customers = query.from(customer)
.where(new JPASubQuery()
.from(customer2)
.where(customer2.id.ne(customer.id),
customer2.lastName.eq(customer.lastName),
customer2.firstName.eq(customer.firstName))
.exists())
.list(customer);

Related

Mapping POJOs and Using Reference in MongoDB using Morphia

I have two model classes. One is Company.java, another is HumanResource.java.
Company.java
#Entity("companies")
public class Company {
#Id
private ObjectId id = new ObjectId();
private String companyName;
private String emailAddress;
private String pictureUrl;
#Reference
private List<HumanResource> humanResources;
...
HumanResource.java
#Entity("humanresources")
public class HumanResource {
#Id
private ObjectId id = new ObjectId();
private String firstName;
private String lastName;
private String emailAddress;
#Reference
private Company company;
...
What I want to achieve is when I save a list of companies to datastore, related list of human resources documents should be inserted automatically.
In addition, I declared
#Id
private ObjectId id = new ObjectId();
in every model class. Is it a good way or should I change it ?
Morphia will not call save() on those references. You must call save() on the instances you want to persist. You can pass in a list of instances so you needn't loop, necessarily, but each instance needs to get passed in explicitly.

How to adapt a child node in sling model of aem6

I am learning to use one of the new features of AEM6 - Sling Models. I have already fetched the properties of a node following the steps described here
#Model(adaptables = Resource.class)
public class UserInfo {
#Inject #Named("jcr:title")
private String title;
#Inject #Default(values = "xyz")
private String firstName;
#Inject #Default(values = "xyz")
private String lastName;
#Inject #Default(values = "xyz")
private String city;
#Inject #Default(values = "aem")
private String technology;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getTechnology() {
return technology;
}
public String getTitle() {
return title;
}
}
and adapted it from a resource
UserInfo userInfo = resource.adaptTo(UserInfo.class);
Now i have the hierarchy as -
+ UserInfo (firstName, lastName, technology)
|
+ UserAddress (houseNo, locality, city, state)
Now I want to fetch the properties of the UserAddress.
I had got some hints from the documentation page, such as -
If the injected object does not match the desired type and the object implements the Adaptable interface, Sling Models will try to adapt it. This provides the ability to create rich object graphs. For example:
#Model(adaptables = Resource.class)
public interface MyModel {
#Inject
ImageModel getImage();
}
#Model(adaptables = Resource.class)
public interface ImageModel {
#Inject
String getPath();
}
When a resource is adapted to MyModel, a child resource named image is automatically adapted to an instance of ImageModel.
but I don't know how to implement it in my own classes. Please help me out with this.
It sounds like you need a separate class for the UserAddress to wrap the houseNo, city, state and locality properties.
+ UserInfo (firstName, lastName, technology)
|
+ UserAddress (houseNo, locality, city, state)
Just mirror the structure you outlined in your Sling Models.
Create the UserAddress model:
#Model(adaptables = Resource.class)
public class UserAddress {
#Inject
private String houseNo;
#Inject
private String locality;
#Inject
private String city;
#Inject
private String state;
//getters
}
This model can then be used in your UserInfo class:
#Model(adaptables = Resource.class)
public class UserInfo {
/*
* This assumes the hierarchy you described is
* mirrored in the content structure.
* The resource you're adapting to UserInfo
* is expected to have a child resource named
* userAddress. The #Named annotation should
* also work here if you need it for some reason.
*/
#Inject
#Optional
private UserAddress userAddress;
public UserAddress getUserAddress() {
return this.userAddress;
}
//simple properties (Strings and built-in types) omitted for brevity
}
You can tweak the behaviour with additional annotations for default values and optional fields but this is the general idea.
In general, Sling Models should be able to handle an injection of another model as long as it finds an appropriate adaptable. In this case, it's another Sling Model but I've done it with legacy classes based on adapter factories as well.

JPA Mapping embedded fields with createNativeQuery

I have an entity with has a field which represents composite primary key annotated with embeddeid and another field which is annotated with embedded annotation.
Both of these fields are not directly mapped with the the columns returned by the query passed to createNativeQuery method.
The getResultList returns me the list of entities, but the two fields which I mentioned are null in all the entities.
public interface Key{
public int hashCode()
}
#Embeddable
public class CompositePK impements Key{
private int empid;
private Date startdate;
private Date enddate;
}
#Embeddable
public class PartitionKey implements Key{
private String empname;
}
#Entity
public class Employee {
#EmbeddedId
private CompositePK id;
#Embedded
private PartitionKey name;
#Column(name="empid")
private int empid;
#Column(name="empname")
private String empname;
#Column(name="startdate")
private Date startdate;
#Column(name="enddate")
private Date enddate;
}
public class Loader{
private static EntityManager em;
public static void main(String [] args){
//code to instantiate em goes here
//...
//....
Query query = em.createNativeQuery("select empid,empname,startdate,enddate from employees", Employee.class );
List entities = query.getResultList();
//print the list
System.out.println(entities);
}
}
The outcome of this is that the entities are populated but their fieldsid and name which are emdedded fields are null. Can anyone please suggest how to populate these two fields?
Thanks

Can i user instance method in JPA entity?

public class Dept{
private String id;
private String name;
private String address;
private List<Student> students;
public static List <Student> getStudentByDeptid(EntityManager em, Dept dept)
{
..............
}
}
getStudentByDeptid() should be static or non static?
Yes you can. But you shouldn't JPA entity are not designed to have business logic in them you should use Session Bans for the same. You can define a StudentBean as session bean and define this logic in that bean.
Assuming you are calling query on em passed to function.

#IdClass JPA Annotation

Here is a composite primary key for one of my entities.
public class GroupMembershipPK implements Serializable{
private static final long serialVersionUID = 7816433876820743311L;
private User user;
private Group group;
public GroupMembershipPK(){
}
public boolean equals(Object o){
if(o==null){
return false;
}
if(o instanceof GroupMembershipPK){
final GroupMembershipPK groupMembershipPK=(GroupMembershipPK)o;
return groupMembershipPK.group.getGroupName().equals(this.group.getGroupName()) &&
groupMembershipPK.user.getName().equals(this.user.getName());
}
return false;
}
public int hashCode(){
return super.hashCode();
}
}
Heres my entity(part of) using the above as a Composite Primary Key.
#Entity
#IdClass(GroupMembershipPK.class)
public class GroupMembership extends AbstractModelElementVersionOther{
private static final long serialVersionUID = 9188465566607060376L;
private String memType;
private Group group;
private User user;
public GroupMembership(){
super();
}
#Column(nullable=false)
public String getMemType(){
return this.memType;
}
public void setMemType(String memType){
this.memType=memType;
}
#Id
#ManyToOne
#JoinColumn(name="groupId")
public Group getGroup(){
return this.group;
}
public void setGroup(Group group){
this.group=group;
}
#Id
#ManyToOne
#JoinColumn(name="userId")
public User getUser(){
return this.user;
}
public void setUser(User user){
this.user=user;
}
#Override
public boolean equals(Object o) {
//
I am a little confused on what should be the equals method implementation for the above entity. How can I compare two composite primary keys?
Any comments on other parts of my code are welcome too.
It is not a good idea you store entities as primary key. There is some limitations when using query language and JPA 1.0 does not support. Besides it there is no need to use entities as primary key. Think about it.If you want, take a special look at the following question
A class that behaves like #Entity and #Embeddable
Answer one
Comment about answer one
You will see that using a entity as primary key is not necessary.
Instead of
public class GroupMembershipPK implements Serializable {
private User user;
private Group group;
}
Use
public class GroupMembershipPK implements Serializable {
private Integer userId;
private Integer groupId;
}
equals implementation is important because JPA compares two entities by using it (JPA checks whether an entity is in persistence context by using equals implementation). So you can implement according to
public boolean equals(Object o) {
if(o == null)
return false;
if(!(o instanceof GroupMembershipPK))
return false;
GroupMembershipPK other = (GroupMembershipPK) o;
if(!(getUserId().equals(other.getUserId()))
return false;
if(!(getGroupId().equals(other.getGroupId()))
return false;
return true;
}
Advice: it is a good idea you use property access instead of field access because, at some times, JPA implementation uses a proxy object because of performance issues. A proxy object makes use of property access because it allows JPA implementation hits the database when necessary.
How to save an object that uses a composite primary key ?
User user = new user();
Group group = new Group();
entityManager.save(user);
entityManager.save(group);
entityManager.flush();
UserGroup userGroup = new UserGroup();
userGroup.setId(new UserGroup.UserGroupId(user.getId(), group.getId()));
entityManager.save(userGroup);
Do you want to know how to implement UserGroup ?
public class UserGroup {
private UserGroupId id;
// You can create UserGroupId outside UserGroup class
// Feel free to choice your best approach
#Embeddable
public static class UserGroupId implements Serializable {
private Integer userId;
private Integer groupId;
// required no-arg constructor
public UserGroupId() {}
public UserGroupId(Integer userId, Integer groupId) {
this.userId = userId;
this.roupId = groupId;
}
// getter's and setter's
// equals and hashcode as shown above
}
#EmbeddedId
public UserGroupId getId() {
return this.id;
}
public setId(UserGroupId id) {
this.id = id;
}
}
Another approach to use composite primary key is IdClass. See IdClass
regards,
It was mentioned partially, anyway:
When implementing the equals method, you should use instanceof to allow comparing with subclasses. If Hibernate lazy loads a one to one or many to one relation, you will have a proxy for the class instead of the plain class. A proxy is a subclass. Comparing the class names would fail.
More technically, you should follow the Liskovs Substitution Principle and ignore symmetry.
The next pitfall is using something like name.equals(that.name) instead of name.equals(that.getName()). The first will fail, if that is a proxy.
http://www.laliluna.de/jpa-hibernate-guide/ch06s06.html