CriteriaBuilder Parent multiselect with child object - parent-child

I'm trying Build criteriaQuery with a parent child entities, I need to use multiselect for selected fields for parent and selected fields for child, not able to pull all the children with fields
#Data
#Entity
#NoArgsConstructor
#Table( name = "Orders" )
public class Orders {
#Id
#Column( name = "ORDER_ID" )
private String orderId;
...
#OneToMany(cascade= CascadeType.ALL, mappedBy = "order")
#NotFound(action = NotFoundAction.IGNORE)
private List<Contact> contacts;
...
}
#Data
#Entity
#NoArgsConstructor
#Table( name = "CONTACT" )
public class Contact {
#Id
#Column( name = "ORDER_ID" )
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn (name="ORDER_ID",referencedColumnName="ORDER_ID",insertable=false, updatable=false)
private Order order;
...
}
My Query implementation
List<String> fields ={"OrderId","OrderName","OrderDate"};
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
Root<Order> root = cq.from(Order.class);
ListJoin join = root.joinList("contacts");
Subquery<Contact> squery = criteriaQuery.subquery(Contact.class);
Root<Contact> contactRoot = squery.from(Contact.class);
Join<Contact, Order> join2 = contactRoot.join("order");
squery.select(contactRoot).where(criteriaBuilder.equal(join, root));
Predicate predicate = specification.toPredicate(root,cq, cb);
List<Selection<?>> selections=new ArrayList<>();
fields.forEach(field -> selections.add(root.get(field).alias(field)));
cq.multiselect(selections);
cq.where(predicate);
TypedQuery<Tuple> typedQuery=entityManager.createQuery(cq);
return typedQuery.getResultList();
I see the join is correct, but select clause is not including any children. Any one came across this>

Related

Unable to deserialize Json that contain 2 objects with the same ID using jackson

I have used jackson JsonIdentityInfo to handle the recursive object reference in spring mvc.
I came across one issue i.e., Unable to deserialize Json that contain 2 objects with the same ID.
{
"organizations": [
{
"organizationId": 1,
"organizationName": "org1",
"enterprise": {
"enterpriseId": 1,
"enterpriseName": "ent1",
"organizations": null
}
},
{
"organizationId": 2,
"organizationName": "org2",
"enterprise": 1
}
]
}
if you see above, both organizations are mapped with enterprise "1". For the first organization it is whole enterprise object but for organization 2, it is giving ID only.
I need to get the whole object for organization 2 as well.
My POJO declarations:
#Entity
#Table(name = "organization")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "organizationId")
public class Organization implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "organization_id")
private Long organizationId;
...
#ManyToOne
#JoinTable(name = "enterprise_organization", joinColumns = {
#JoinColumn(name = "organization_id") }, inverseJoinColumns = { #JoinColumn(name = "enterprise_id") })
private Enterprise enterprise;
...
}
#Entity
#Table(name = "enterprise")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "enterpriseId")
public class Enterprise extends BaseEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "enterprise_id")
private Long enterpriseId;
...
#OneToMany(mappedBy = "enterprise")
private List<Organization> organizations;
...
}
I searched google and SO but no luck.
What are the changes needed to deserialize Json that contain 2 objects with the same ID ?
After a lot of tries, #JsonIgnoreProperties solved my problem.
example: "#JsonIgnoreProperties(allowSetters = true, value = { "enterprise" })"

Entity Manager is not fetching child records after adding data

I am using entity manager to persist data into the database. Data is inserting successfully, but when try to fetch the data it doesn't fetch the child data.
Incident.java
#Entity
#Table(name = "Incident")
public class Incident {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "incidentID")
private Integer incidentID;
#Column(name = "incidentTitle")
private String incidentTitle;
#Column(name = "date")
#JsonFormat(pattern = "yyyy-MM-dd")
private Date incidentDate;
#Column(name = "incidentContent")
private String incidentContent;
#ManyToOne
#JoinColumn(name = "countryID")
private Country country;
// Getter and setters
}
Country.java
#Entity
#Table(name="Country")
public class Country {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#NotNull
#Column(name = "name")
#Size(min = 8, max = 100)
private String name;
// getter and setters
}
DAO.java
public Incident addIncident(Incident incident) {
em.getTransaction().begin();
em.persist(incident);
em.flush();
em.getTransaction().commit();
return incident;
}
When i add data into incident table, countryId added successfully but when i try to fetch the same record, countryId comes but name doesn't come.
But when i try to update same record or bounce server or redeploy the application then all data comes successfully along with name.
Couldn't understand the issue.
Can you please help me.

Hibernate cannot simultaneously fetch multiple bags for Parent-Children-Grandchildren unidirectional association

Straightforward to the point. I am given Hibernate exception Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags.
I have 3 entities in a Parent --(1-*)--> Child --(1-*)--> Grandchild unidirectional relationship:
NetworkElement -> NetworkElementInterface -> NetworkElementInterfaceCounters
Over both relationship I have defined FetchType.LAZY.
#Entity
#Table(name = "NETWORK_ELEMENTS")
public class NetworkElement extends Device {
#Id
#Column(name = "ID_DEVICE")
private Long id;
#ManyToOne(targetEntity = DeviceLocation.class, fetch = FetchType.LAZY)
#JoinColumn(name = "ID_DEVICE_LOCATION")
private DeviceLocation deviceLocation;
#Column(name = "MODEL", length = 30)
private String model;
#Column(name = "TYPE", length = 30)
private String type;
#Column(name = "IMAGE", length = 50)
private String image;
#OneToMany(orphanRemoval = true, fetch = FetchType.LAZY, targetEntity = NetworkElementInterface.class, cascade=CascadeType.ALL)
#Size(min = 0, max = 99)
private List<NetworkElementInterface> interfaces;
}
#Entity
#Table(name = "NETWORK_ELEMENT_INTERFACES")
public class NetworkElementInterface {
#Id
#Column(name = "ID_NETWORK_ELEMENT_INTERFACES")
protected Long id;
#Column(name = "NAME")
private String name;
#Column(name = "SPEED")
private Long speed;
#Column(name = "DUPLEX")
private String duplex;
#ElementCollection(fetch = FetchType.LAZY)
#CollectionTable(name = "NETWORK_ELEMENT_INTERFACE_COUNTERS", joinColumns = #JoinColumn(name = "ID_NETWORK_ELEMENT_INTERFACE"))
#Type(type = "com.netsuite.wind.entity.NetworkElementInterfaceCounters")
private List<NetworkElementInterfaceCounters> interfaceCountersHistory;
}
#Embeddable
public class NetworkElementInterfaceCounters {
private Long inputErrors;
private Long inputDrops;
private Long inputDiscards;
private Long inputCRCErrors;
private Long inputFifoErrors;
private Long outputErros;
private Long outputDrops;
private Long outputCRCErrors;
private Long outputFifoErrors;
}
What I am trying to achieve is:
1) in my DAO to create a method which will return Parent fully populated with its children and grandchildren. (NetworkElement -> NetworkElementInterface -> NetworkElementInterfaceCounters).
1b) (not really important here, just curious) Eventually I would also like to populate children of a different type, in my NetworkElement DeviceLocation object along with populated NetworkInterfaces.
My DAO Method of NetworkElement:
#Transactional()
#SuppressWarnings("unchecked")
public NetworkElement getByIdWithInterfaces(Long id) {
final Session session = sessionFactory.getCurrentSession();
------------------------------------------------------
// This works well when I only want children to by populated
Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces WHERE ne.id = :id");
------------------------------------------------------
// This doesn't work when I also try to fetch grandchildren. I am given Hibernate exception: "cannot simultaneously fetch multiple bags"
Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces nei JOIN FETCH nei.interfaceCountersHistory WHERE ne.id = :id");
------------------------------------------------------
// Eventually I tried "FETCH ALL PROPERTIES" which also doesn't work.
Query query = session.createQuery("FROM NetworkElement ne FETCH ALL PROPERTIES WHERE ne.id = :id");
------------------------------------------------------
query.setParameter("id", id);
NetworkElement result = null;
try {
result = (NetworkElement) query.uniqueResult();
} catch (NoResultException e) {
e.printStackTrace();
}
return result;
}
So for:
1) Query query = session.createQuery("SELECT ne FROM NetworkElement ne JOIN FETCH ne.interfaces nei JOIN FETCH nei.interfaceCountersHistory WHERE ne.id = :id");
Try to make it work.
I think I am missing somewhere some annotation in order to avoid this kind of exception. I noticed in some examples they were using #IndexColumn but this annotation is deprecated.. Appreciate any directions for this.

Unable to serialize custom object activeandroid

I am trying to store some custom object as a blob in SqlLite db. The object is a field of a class extending Model. All other fields (of primitive types) go successfully in the DB, but the custom one - it is null always.
#Table(name = "data")
public class Data extends Model {
#Column(name = "number")
private int number;
#Column(name = "blob")
private Contact blob;
...
This is how i store the entity
Data data = new Data(0, new Contact(id, name, number));
data.save();
Here is the contact class
public class Contact {
private String id;
private String name;
private String number;
...
I believe a TypeSerializer is needed, so I've created one.
public class ContactSerializer extends TypeSerializer {
private static final String ELEMENTS_DELIMITER = ";";
#Override
public Object deserialize(Object asString) {
String[] afterSplit = ((String) asString).split(ELEMENTS_DELIMITER);
return new Contact(afterSplit[0], afterSplit[1], afterSplit[2]);
}
#Override
public Class<?> getDeserializedType() {
return Contact.class;
}
#Override
public SerializedType getSerializedType() {
return SerializedType.STRING;
}
#Override
public Object serialize(Object asContact) {
Contact temp = (Contact) asContact;
return temp.getId() + ELEMENTS_DELIMITER + temp.getName() + ELEMENTS_DELIMITER
+ temp.getNumber();
}
}
When i query the db I got object with this particular field "Contact" as null always. Where might be the problem? Do I need to specify which is the TypeSerializer for my object? Or the implementation of TypeSerializer I've created is wrong?
You also need to extent Contact from Model:
#Table(name = "contact")
public class Contact extends Model{
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#Column(name = "number")
private String number;
}
Now everything should work out of the box. It's a bit late for a response but perhaps I will help someone else.

one-to-many detached Criteria parent table fetch based on child table

i have one problem in one-to-many mapping using hibernate.
i have 2 classes, Person and Address. Person is mapped by Address ( one-to-many)
i want get all Person where Address = "xxxx";. how to prepare this query using DetachedCriteria . below i have added a piece of code from my dao class. please help me to complete it.
Person.java
#Entity
#Table(name="PERSON")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="personId")
private int id;
#Column(name="personName")
private String name;
#OneToMany(cascade =CascadeType.ALL,fetch = FetchType.LAZY)
#JoinColumn(name="personId")
private Set <Address> addresses;
}
Address.java
#Entity
#Table(name = "ADDRESS")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "addressId")
private int id;
#Column(name = "address",nullable=false)
private String address;
#ManyToOne(cascade =CascadeType.ALL)
#JoinColumn(name="personId",nullable=false)
private Person person;
}
My DAO
DetachedCriteria c = DetachedCriteria.forClass(Person.class);
List<Person> persnList =null;
/*here i want add some restriction for
fetch all person whose address = "abcd"
here address is collection. how to set restriction in it ?.
*/
persnList = getHibernateTemplate().findByCriteria(c);
System.out.println(persnList.size());
select * from person where Address.address = "xxxx"; how to implement this using DetachedCriteria ?
DetachedCriteria c = DetachedCriteria.forClass(Person.class);
List<Person> persnList =null;
DetachedCriteria addrCrit = c.createCriteria("addresses").addRestriction(Restrictions.eq("address","abcd"));
addrCrit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
persnList = getHibernateTemplate().findByCriteria(c);
System.out.println(persnList.size());
Creating inner criteria on main criteria which will do an equivalent inner join.

Resources