Hi,
Recently I was able to find help here, so I will ask for such again. I am helping in resolving some problem and every opinion is important. We are having two tables Application and BusinessUnit represented by ApplicationBean and BusinessUnitBean. They have many to many relation. Every application can have many units assigned to it. Every application have some basic properties and a set of units that represents the manyToMany relation. The BusinessUnit on the other hand has also some basic properties and ManyToOne relation to itself because every unit can have a parent unit. The problem is that we are testing the creation of 1500 applications and every application can have from 60 to 120 units. When we try to select all applications, the result is retrieved too slow. The result from the big join query in hibernate is fast, but the initialization of the collection as objects is slow. So we have decided to fetch only the necessary properties per case, it is very fast when we do not need the set with units, but now we need them or at least their ids. With projection we can get the applications with only some properties initialized. But is it possible to get the list with all units per application, but only with id initialized for every unit. These are the beans:
Code:
public class ApplicationBean implements Application, Cloneable {
/** Unique application name. */
@Column(name="name", nullable = false)
@AuditedProperty(name = "Name")
private String mName = null;
/** Application type. */
@Column(name="type", nullable = false, updatable = false)
@AuditedProperty(name = "Type")
private String mApplicationType = null;
/** Notes for this application. */
@Column (name="notes", length=2048)
@AuditedProperty(name = "Notes")
private String mNotes = null;
@ManyToMany(fetch=FetchType.EAGER, targetEntity=BusinessUnitBean.class)
@JoinTable(name="Application_BusinessUnit", joinColumns = @JoinColumn(name="applicationId", nullable=false),
inverseJoinColumns=@JoinColumn(name="businessUnitId", nullable=false),
foreignKey = @ForeignKey(name="FKApplication_BusinessUnit"),
inverseForeignKey = @ForeignKey(name="FKBusinessUnit_Application")
)
@org.hibernate.annotations.Cascade( { org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.REPLICATE, org.hibernate.annotations.CascadeType.MERGE })
@Fetch(FetchMode.SELECT)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region="ApplicationCache")
@AuditedProperty(name = "Business units", nameOnly = true)
private Set<BusinessUnit> mBusinessUnits = new HashSet<BusinessUnit>();
/**
* The unique identifer for this object. Created and managed by the persistence implementation.
*/
@XmlAttribute (name="id", required=false)
@javax.persistence.Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "some.class.Uuid")
@Column(name = "id", length=32)
private String mUniqueId = null;
//some other properties
}
public class BusinessUnitBean implements BusinessUnit, Cloneable {
/** Unique name. */
@Column(name="name", nullable=false)
@AuditedProperty(name = "Name")
private String mName = null;
/** Unique id object of the parent business unit. */
@ManyToOne(fetch=FetchType.EAGER, targetEntity=BusinessUnitBean.class)
@JoinColumn(name="parentId", foreignKey = @ForeignKey(name="FKBusinessUnit_Parent"))
@AuditedProperty(name = "Parent business unit", nameOnly = true)
private BusinessUnit mParent = null;
/**
* The unique identifier for this object. Created and managed by the persistence implementation.
*/
@XmlAttribute (name="id", required=false)
@javax.persistence.Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "some.class.Uuid")
@Column(name = "id", length=32)
private String mUniqueId = null;
//some other properties
}
I will be very grateful to anyone that has some idea. For now we have tried to do a inner join without Hibernate between the Application and Application_BusinessUnit table in order to get all the ids of units per specific application. But it is still pretty slow. I have tried something but it works only when stripping the simple properties. When I want only Application with id, name and type, I use a named query like "@NamedQuery(name = "findAllApplicationNames", query = "select new ApplicationBean(mUniqueId, mName, mApplicationType) from ApplicationBean order by mName asc")". But when I have tried to add the set with units in the constructor, there were some problems, I can not use a set in the named query. The same was tried with projection also.
Thank you.