Is there any way to obtain Object array of Java Bean fields? I have some bean classes that represent database tables (Hibernate) and I need to retrieve from them Object arrays for jtable model, but it seems that the only way to do this is by calling getXXX methods for each field of each class - a lot of work to do.
If you want a generic way to extract values from a bean, you should look at introspection (package "java.lang.reflect").
Here is a basic example:
Field[] fields = ABeanClass.getDeclaredFields();
Object[] values = new Object[fields.length];
int i = 0;
for (Field field : fields) {
values[i] = field.get(beanInstance);
i++;
}
The way i do it is use a "controller" class which handles all the communication between the model and the database.
You make List of the "objects" like for example private List myList = null;
Now, write a generic method in the controller class. say getList which returns the list. You pass the relative class to the method and it returns you the list using the hibernate session. In your bean, do this
myList = myController.getList(YourBean.class);
And this should be your getlist method.
public List getList(Class c) throws BaseExceptionHandler {
Session session = null;
Transaction tx = null;
String query = null;
List list = null;
try {
query = getStringQuery(c);
if (query != null) {
session = sessFactory.openSession();
tx = session.beginTransaction();
list = (List) session.createQuery(query).list();
tx.commit();
}
} finally {
if (session != null) {
session.close();
}
}
return list;
}
CHEERS :)
Related
I am working on a java application with Spring and JDBC connection.
I did not code the application myself and I am kind of new to some of the frameworks and implications of this.
I traced the path of how sql statements are passed, however I am stuck at some point where I do not find any details on the method that is called and the class it belongs to.
The method is imported via import de.dit.icr.frontend.ProxyBean;
Basically all queries are contained in a single "query.xml" file, that is passed into a "ProxyBean" object, which is then fed with the parameters map and then a "getStatement()" method is called that returns the prepared query string.
What I would like to do is to split the query.xml file into single sql files (one for each query) and implement a new method instead of the proxyBean.getStatement(), that would still take the parameters map, the name of the query, and prepare the statement.
In order to do that, I require your light on something:
- where does this ProxyBean class come from? From an external library, and if so, which one?
- Which method, which library could I use to create a string of an sql prepared statement from a sql file and a parameters map?
Thanks a lot for your help!
Here is a simplified view of the code:
import de.dit.icr.frontend.ProxyBean;
import de.dit.icr.util.Url;
import de.dit.itsales.dbi.util.DBUtil;
import de.dit.itsales.dbi.util.Log;
public class IASAdapterImpl implements IASAdapter {
private static final String[] QUERY_FILES = {"query.xml"};
private static final String RELATIVE_PATH_TO_QUERY_FILE = "queries";
public IASAdapterImpl() {
init();
}
private void init() {
String key = "queries";
String pathToQueryFile = DBUtil.getInstance().getConfigDir() + RELATIVE_PATH_TO_QUERY_FILE;
Url.register(key, pathToQueryFile);
createProxyBean();
}
public synchronized String getQuery(String queryName, Map<String,String> queryVariables, boolean resolveNames) {
ProxyBean proxyBean = createProxyBean();
setParameter(queryVariables, proxyBean);
String temp = proxyBean.getStatement(queryName, resolveNames);
return temp;
}
private ProxyBean createProxyBean() {
ProxyBean bean = new ProxyBean();
for (int i = 0; i < QUERY_FILES.length; i++) {
bean.setQuerySet(QUERY_FILES[i]);
}
return bean;
}
private void setParameter(Map<String,String> map, ProxyBean bean) {
if(map == null || map.isEmpty()) {
return;
}
for (Map.Entry<String,String> entry : map.entrySet()) {
String key = entry.getKey();
bean.set(key, entry.getValue());
}
}
Sample of query.xml:
<query name = "alle-fonds"><![CDATA[
select fondsnummer,
spokid,
mfnummer,
fondsname,
bewertungsdatum,
letztebewertung,
hauptfonds,
performancegraphrelevant
from rep.v_alle_fonds where anwender_login = '${loginname}'
and sprache = lower('${sprache}')
order by mfnummer
]]></query>
The task is to retrieve data from the database for certain list of columns and return as custom already existing class.
I tried to resolve this task with following code:
public List<EntityOne> getServiceProviders(EntityTwo EntityTwo) {
Criteria criteria = createCriteria(EntityOne.class);
criteria.add(Restrictions.eq("EntityTwo", EntityTwo));
criteria.createAlias("spid", "two");
criteria.addOrder(Order.asc("two.entityName"));
criteria.setProjection(Projections.projectionList()
.add(Projections.property("entityId"), "entityId")
.add(Projections.property("publishStatus"), "publishStatus")
.add(Projections.property("two.entityName"), "two.entityName")
.add(Projections.property("two.entityId"), "two.entityId")
);
return criteria.list();
}
But I receive a list of data that is not grouped in class as I wanted.
Your question is not very clear especially where you are attempting to use Restrictions.eq("EntityTwo", EntityTwo) as this will not give proper results. Hibernate however provides a means to return EntityOne as an Object from the Columns selected using Hibernate Transformers class. In your case, you will need to write a custom class with getter setter of the columns you are returning. Note that is is important that the variables be named exactly like the alias columns.
Since your example is not clear, let me illustrate with a simple example: Say I need all purchase OrderAmount grouped by OrderDate and OrderNumber
public static List<YourCustomEntity> getAggregateOrders(){
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
List<YourCustomEntity> list = new ArrayList<YourCustomEntity>();
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(PurchaseOrders.class);
cr.setProjection(Projections.projectionList()
.add(Projections.sum("orderAmount").as("sumOrderAmount"))
.add(Projections.groupProperty("orderNumber").as("agOrderNumber"))
.add(Projections.groupProperty("orderDate").as("agOrderDate")));
cr.setResultTransformer(Transformers.aliasToBean(YourCustomEntity.class));
list = (List<YourCustomEntity>) cr.list();
}catch (Exception asd) {
System.out.println(asd.getMessage());
if (tx != null) {
tx.rollback();
}
} finally {
session.close();
}
return list;
}
In this regard, you will need your customEntity to have the three columns returned above. For example:
public class YourCustomEntity {
private double sumOrderAmount;
private String agOrderNumber;
private Date agOrderDate;
//And then the getters and setters
NB: Notice the naming of the variables is the same as the column aliases.
You should use Projections.groupProperty(propertyName);
criteria.setProjection(Projections.groupProperty("propertyName"));
I am using JPAs criteria api to request some objects form my database and apply filter to the request.
the following code shows the method that assambles and executes the query:
#Override
public List<MyClass> findAll(MyClassFilterObject filter) {
final CriteriaBuilder builder = this.getEntityManager().getCriteriaBuilder();
final CriteriaQuery<MyClass> criteriaQuery = builder.createQuery(MyClass);
Root<MyClass> root = criteriaQuery.from(MyClass);
List<Predicate> criteriaList = new LinkedList<Predicate>();
if (!filter.getMyClassStatus().equals("")) {
Path<String> statusPath = root.get("MyClassStatus");
criteriaList.add(builder.equal(statusPath, MyClassStatus.valueOf(filter.getMyClassStatus())));
}
if (!filter.getMyClassType().equals("")) {
Expression<Set<MyClassType>> MyClassTypesQuery = root.get("MyClassType");
criteriaList.add(builder.isMember(MyClassType.valueOf(filter.getMyClassType()), MyClassTypesQuery));
}
if (criteriaList.size()>0){
criteriaQuery.where(builder.and(criteriaList.toArray(new Predicate[criteriaList.size()])));
}
TypedQuery<MyClass> typedQuery = this.getEntityManager().createQuery(criteriaQuery);
typedQuery.setFirstResult(filter.getPagenumber() * 10);
typedQuery.setMaxResults(10);
List<MyClass> MyClasss = typedQuery.getResultList();
if (MyClasss.isEmpty()) {
return new LinkedList<MyClass>();
}
return MyClasss;
}
this code always returns the same two objects, no matter what i choose as "MyClassType".
MyClass has a set of MyClassType (an Enum value) objects attached and i want to know if the MyClassType object from my filter is a member of this collection
I am not sure if i am using the isMember method right
I am working on a project where using JPA and the following code I am able to retrieve from DB a list of objects which consist the profile of a user. Each object is a two field object (word, frequency)
public class JpaUserprofilesDao implements UserProfilesDao {
#PersistenceUnit
private EntityManagerFactory emf;
EntityManager em;
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
#Transactional
#Override
public List<Object[]> getUserProfiles(Long userId){
em = getEntityManager();
try {
List<Object[]> up =em.createQuery("SELECT up.userprofilesPK.word, up.userprofilesPK.frequency from Userprofiles up WHERE up.userprofilesPK.userid= :userid").setParameter("userid", userId).getResultList();
return up;
} finally {
em.close();
}
}
}
In another class of my project I am using the following block of code in order to put the above information in a Map and be able to manipulate it.
profileObject = peristanceservice.getUserProfiles(userId);
for(Object[] s: profileObject ){
if(!tempList.contains(s[0].toString())){
bag.put( (String) s[0].toString(), Integer.parseInt(s[1].toString()) );
tempList.add(s[0].toString());
}
}
Even though I am getting the result it takes so long time to process the list of objects returned by the persistance service and putting them to the Map, that finally prove useless.
Is there a way to get the Map directly from the persistance service?
Thank you in advance.
this is not exactly what you want, but you can use it.
You can transform List to Map using Guava
Use Maps.uniqueIndex:
Returns an immutable map for which the Map.values() are the given elements in the given order, and each key is the product of invoking a supplied function on its corresponding value.
Example:
Map<String,String> mappedRoles = Maps.uniqueIndex(yourList, new Function<String,String>() {
public String apply(String from) {
// do stuff here
return result;
}});
In Hibernate, is there a way to create an add an Alias to a Criterion object. I have the following to work with:
I have a dynamic search from big Database with many tables. The search has many (25+) optional non-exclusive parameters selected clien-side. This requires the use of the Hibernate Criteria API for managability. In my DAO I have the following method:
Public List<myPojoClass> getDataByCriterion( List<Criterion> restrictionList) {
Session s = HibernateUtil.currentSession();
Criteria c = s.createCriteria(myPojo.class);
for (Criterion crit : restrictionList){
c.add(crit);
}
List<myPojoClass> response = c.list();
return response;
}
I need to do a Join with myOtherPojo.class and would like to know if it is possible to add an alias to the Criteria list above.
Somthing like :
restrictionsList.add(... ...createAlias("myOtherPojo.class" , "mop");
then, I need o add other Logical and to this class as above.
You again! ;)
You could pass a collection of entries (like a HashMap<String, String>) and iterate over them to populate your aliases... like this:
Public List<myPojoClass> getDataByCriterion( List<Criterion> restrictionList, HashMap<String,String> aliases) {
Session s = HibernateUtil.currentSession();
Criteria c = s.createCriteria(myPojo.class);
for (Criterion crit : restrictionList){
c.add(crit);
}
for (Entry<String, String> entry : aliases.entrySet()){
c.createAlias(entry.getKey(), entry.getValue());
}
List<myPojoClass> response = c.list();
return response;
}
You could do something similar if you want to change the fetch modes. Of course the calling method needs to know the data model so it can set up the aliases properly, otherwise you can get errors at runtime.
from what I know there is now way to create joins without instance of Criteria. I suggest you create some wrapper for criteria which would contain criteria and alias definition if necessary and then use Criteria as visitor (like from this Pattern)
interface CriterionWrapper {
void visit(Criteria c);
}
class OnlyCriterionWrapper implements CriterionWrapper {
private Criterion c;
public void visit(Criteria c){c.add(c);}
}
class CriterionWrapper implements CriterionWrapper{
private Criterion c;
private String whateverIsNeededToCreateAlias
public void visit(Criteria c){
c.createAlias(whateverIsNeededToCreateAlias);
c.add(c);
}
}
and then pass List as parameter to your getDataByCriterion() method