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

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.

Related

Spring Boot "Cannot add foreign key constraint"

I have a spring boot rest service with the following model classes -
Report class -
#Entity
#Table (name = "report")
#EntityListeners(AuditingEntityListener.class)
public class Report {
#Id
#Column (name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "from_user_id", nullable = false)
private Long fromUserId;
#Column(name = "to_user_id", nullable = false)
private Long toUserId;
#Temporal(TemporalType.DATE)
#JsonFormat(pattern = "dd-MM-yyyy hh:mm:ss")
#CreatedDate
private Date createdAt;
#Column(nullable = false)
private String observation;
[ OTHER VARS AND GETTERS AND SETTERS .... ]
}
User class -
#Entity
#Table (name = "user")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String lastName;
#Column(unique = true, nullable = false)
private String email;
#Column(nullable = false)
private String password;
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "to_user_id")
private List<Report> reportReceivedList;
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "from_user_id")
private List<Report> reportSentList;
[GETTERS AND SETTERS .....]
}
This is causing a
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
which in turn is caused by
Caused by: java.sql.SQLException: Cannot add foreign key constraint
I want to create my mapping such that one user can have multiple sent reports and received reports, and once I delete a user, both sent and received reports should get deleted. I have explored loads of links for creating mappings and I am very confused because of different methods given everywhere.

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.

keep records increment jpa-sqlite sqlite

My problem is when I save a person domiciled the id of the person record is 1 and the address 2 and when I save another record the id of person is 3 and the domicile 4 and so is increased, I want to increase as it should be is to record who is 1 and for of registered prox 1 for registration is 2 and 2 the next 3 and 3 and so on.
Then I leave the source code of the entities, the main, the method to keep and what gives me the console when I create the tables. I'm using netbeans 7.4 and EclipseLink library jpa2.1 and jdbc for sqlite dirver
#Entity
public class Persona implements Serializable {
protected static final long serialVersionUID = 1L;
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private Long id;
private String nombre;
#OneToOne (cascade = CascadeType.ALL)
private Domicilio domicilio;
public Persona() {
}
public Persona(String nombre) {
this.nombre = nombre;
domicilio= new Domicilio();
}
public Domicilio getDomicilio() {
return domicilio;
}
public void setDomicilio(Domicilio domicilio) {
this.domicilio = domicilio;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
Entity Domicilio:
#Entity
public class Domicilio implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String calle;
public Domicilio() {
}
public Domicilio(String calle) {
this.calle = calle;
}
public String getCalle() {
return calle;
}
public void setCalle(String calle) {
this.calle = calle;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
Method found in the class PersonaJpaController used to save the record
public void guardar(){
persona= new Persona("angel");
persona.getDomicilio().setCalle("alpatacal");
create(persona);
}
This is my main program
public class Pruebaentidades {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pruebaentidadesPU");
EntityManager em = emf.createEntityManager();// create tables
PersonaJpaController p= new PersonaJpaController(Persistence.createEntityManagerFactory("pruebaentidadesPU"));
p.guardar();
}
}
This is what gives me the console when I create tables
[EL Info]: 2014-01-03 17:27:01.189--ServerSession(24979675)--EclipseLink, version: Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5
[EL Info]: connection: 2014-01-03 17:27:01.379--Not able to detect platform for vendor name [SQLite3]. Defaulting to [org.eclipse.persistence.platform.database.DatabasePlatform]. The database dialect used may not match with the database you are using. Please explicitly provide a platform using property eclipselink.platform.class.name.
[EL Info]: connection: 2014-01-03 17:27:01.446--ServerSession(24979675)--file:/C:/Users/VM/Desktop/Mis Proyectos/Proyectos Netbeans/pruebaentidades/build/classes/_pruebaentidadesPU login successful
[EL Warning]: 2014-01-03 17:27:01.6--ServerSession(24979675)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: near "CONSTRAINT": syntax error
Error Code: 0
Call: ALTER TABLE PERSONA ADD CONSTRAINT FK_PERSONA_DOMICILIO_ID FOREIGN KEY (DOMICILIO_ID) REFERENCES DOMICILIO (ID)
Query: DataModifyQuery(sql="ALTER TABLE PERSONA ADD CONSTRAINT FK_PERSONA_DOMICILIO_ID FOREIGN KEY (DOMICILIO_ID) REFERENCES DOMICILIO (ID)")
for those who have this same problem I want to say that the solution to the problem was to create a sequence for each table and use the strategy generation secuence.
add these statements for each entity allowing me to create a sequence for each table
Entity Persona:
#GeneratedValue (strategy = GenerationType.SEQUENCE, generator = "PERS_SEQ")
#SequenceGenerator ( name = "PERS_SEQ" , sequenceName = "PERS_SEQ")
Entity Domicilio:
#GeneratedValue(strategy = GenerationType.SEQUENCE , generator = "DOM_SEQ")
#SequenceGenerator ( name = "DOM_SEQ" , sequenceName = "DOM_SEQ")

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.

Resources