Find by Object Attributes in JPA - java

i was wondering whether it is possible to find an object using an example object like you can in hibernate with:
Cat cat = new Cat();
cat.Sex = 'F';
cat.Color = Color.Black;
List results = session.CreateCriteria(typeof(Cat)).Add( Example.Create(cat)).List();
I know i can find by primary key, just not looking forward to writing a million lines of findByX, findByY etc etc.
thanks.
Nico

It seems as if the Criteria API is being considered for the next JPA release. There is some discussion about it here.
It would seem that at the moment if you want the Query by Example and Criteria features then you will have to use Hibernate.

so since it's not available in the current JPA API, the only way i can see how to implement it would be by using this:
public <T> List<T> findByAttribute(T object) {
List<T> found = new ArrayList<T>();
Map m = null;
try {
m = BeanUtils.describe(object);
} catch (Exception ex) {
return null;
}
String query = "select c from " + object.getClass().getSimpleName() + " c where ";
if (m != null) {
for (Object key : m.keySet()) {
if (!key.equals("class")) {
Object value = m.get(key);
if (value != null) {
try {
ConvertUtils.convert(m.get(key), PropertyUtils.getPropertyType(object, key.toString()));
query += " c." + key + " = :" + key + " and";
} catch (Exception ex) {
// the reason for this noncy try catch is so that you don't add parameters that are not primitives
}
}
}
}
query = query.substring(0, query.lastIndexOf("and"));
Query q = getEntityManager().createQuery(query);
for (Object key : m.keySet()) {
if (!key.equals("class")) {
if (m.get(key) != null) {
try {
Object o = ConvertUtils.convert(m.get(key), PropertyUtils.getPropertyType(object, key.toString()));
q.setParameter(key.toString(), o);
} catch (Exception ex) {
System.out.println("what we have here is a failure to communicate");
System.out.println("only primitive types allowed");
}
}
}
}
List resultList = q.getResultList();
if (resultList != null) {
found.addAll(resultList);
}
}
return found;
}
but this will only work for primitive types i think. I guess it's something.
Thanks anyway
N

Related

Strings can not be converted to DAO Receiver

I am trying to perform batch insertion operation with a list object but while inserting I am getting String cannot be converted to DAO.The receiver in the iterator loop.
I have tried to list the list object, at that time it is printing values from the list. but, when I use generics are normal list it is showing error and I don't find any solution to insert
From this method I am reading the excel file and storing into list
public List collect(Receiver rec)
{
//ReadFromExcel rd = new ReadFromExcel();
List<String> up = new ArrayList<String>();
//List<String> details = rd.reader();
//System.out.println(details);
try( InputStream fileToRead = new FileInputStream(new File(rec.getFilePath())))
{
XSSFWorkbook wb = new XSSFWorkbook(fileToRead);
wb.setMissingCellPolicy(Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
XSSFSheet sheet = wb.getSheetAt(0);
DataFormatter fmt = new DataFormatter();
String data ="";
for(int sn = 0;sn<wb.getNumberOfSheets()-2;sn++)
{
sheet = wb.getSheetAt(sn);
for(int rn =sheet.getFirstRowNum();rn<=sheet.getLastRowNum();rn++)
{
Row row = sheet.getRow(rn);
if(row == null)
{
System.out.println("no data in row ");
}
else
{
for(int cn=0;cn<row.getLastCellNum();cn++)
{
Cell cell = row.getCell(cn);
if(cell == null)
{
// System.out.println("no data in cell ");
// data = data + " " + "|";
}
else
{
String cellStr = fmt.formatCellValue(cell);
data = data + cellStr + "|";
}
}
}
}
}
up = Arrays.asList(data.split("\\|"));
// System.out.println(details);
}
catch (FileNotFoundException ex)
{
Logger.getLogger(BImplementation.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex)
{
Logger.getLogger(BImplementation.class.getName()).log(Level.SEVERE, null, ex);
}
Iterator iter = up.iterator();
while(iter.hasNext())
{
System.out.println(iter.next());
}
String row="";
Receiver info = null;
String cid = "";
String cname = "";
String address = "";
String mid = "";
boolean b = false;
List<Receiver> res = new ArrayList<Receiver>();
int c = 0;
try
{
String str = Arrays.toString(up.toArray());
//System.out.println(str);
String s = "";
s = s + str.substring(1,str.length());
// System.out.println("S:"+s);
StringTokenizer sttoken = new StringTokenizer(s,"|");
int count = sttoken.countTokens();
while(sttoken.hasMoreTokens())
{
if(sttoken.nextToken() != null)
{
// System.out.print(sttoken.nextToken());
cid = sttoken.nextToken();
cname = sttoken.nextToken();
address = sttoken.nextToken();
mid = sttoken.nextToken();
info = new Receiver(cid,cname,address,mid);
res.add(info);
System.out.println("cid :"+cid+ " cname : "+cname +" address : "+address+" mid : "+mid);
c = res.size();
// System.out.println(c);
}
else
{
break;
}
}
System.out.println(count);
// System.out.println("s");
}
catch(NoSuchElementException ex)
{
System.out.println("No Such Element Found Exception" +ex);
}
return up;
}
with this method I'm trying to insert into database
public boolean insert(List res)
{
String sqlQuery = "insert into records(c_id) values (?)";
DBConnection connector = new DBConnection();
boolean flag = false;
// Iterator itr=res.iterator();
// while(it.hasNext())
// {
// System.out.println(it.next());
// }
try( Connection con = connector.getConnection();)
{
con.setAutoCommit(false);
PreparedStatement pstmt = con.prepareStatement(sqlQuery);
Iterator it = res.iterator();
while(it.hasNext())
{
Receiver rs =(Receiver) it.next();
pstmt.setString(1,rs.getcID());
pstmt.setString(2,rs.getcName());
pstmt.setString(3,rs.getAddress());
pstmt.setString(4,rs.getMailID());
pstmt.addBatch();
}
int [] numUpdates=pstmt.executeBatch();
for (int i=0; i < numUpdates.length; i++)
{
if (numUpdates[i] == -2)
{
System.out.println("Execution " + i +": unknown number of rows updated");
flag=false;
}
else
{
System.out.println("Execution " + i + "successful: " + numUpdates[i] + " rows updated");
flag=true;
}
}
con.commit();
} catch(BatchUpdateException b)
{
System.out.println(b);
flag=false;
}
catch (SQLException ex)
{
Logger.getLogger(BImplementation.class.getName()).log(Level.SEVERE, null, ex);
System.out.println(ex);
flag=false;
}
return flag;
}
I want to insert list object using JDBC batch insertion to the database.
Your method collect(Receiver rec) returns the List of strings called up.
return up;
However (if you are really using the method collect to pass the List into insert(List res) method), you are expecting this list to contain Receiver objects. Which is incorrect, since it collect(..) returns the list of Strings.
And that causes an error when you try to cast Receiver rs =(Receiver) it.next();
You need to review and fix your code, so you will pass the list of Receiver objects instead of strings.
And I really recommend you to start using Generics wherever you use List class. In this case compiler will show you all data-type errors immediately.

How to do a select all using GreenDAO?

Does anyone know how to do a simple select * from table in greenDAO and place it into an entity? I have done some research on this and I am unable to get any simple example. This is what I have so far:
public void storeAppTimeUsageData(AppTimeUsage stats) {
List<AppTimeUsage> items = new ArrayList<>();
//appTimeUsageDao = DeviceInsightApp.getSession(this, true).getAppTimeUsageDao();
try {
// master
appTimeUsageDao.insertOrReplace(stats);
//} catch (IOException e) {
} catch (Exception e) {
Log.e("Error", "Some exception occurred", e);
Log.e("APP_TAG", "STACKTRACE");
Log.e("APP_TAG", Log.getStackTraceString(e));
}
String sql = "SELECT * FROM APP_TIME_USAGE ";
Cursor c = appTimeUsageDao.getDatabase().rawQuery(sql, null);
int offset = 0;
int d ;
int cd ;
String e = "";
while (c.moveToNext()) {
AppTimeUsage atu AppTimeUsage(
c.getLong(0);
//long b = c.getInt(0);
d = c.getInt(2);
e = c.getString(3);
break;
);
items.add(atu);
}
}
GreenDAO already comes with a built-in method for achieve this task. In your case:
List<AppTimeUsage> items = appTimeUsageDao.loadAll();
This will select all records from APP_TIME_USAGE and return a List<AppTimeUsage> containing the entities.

Hibernate sql error:java.lang.String cannot be cast to java.lang.Integer

I change Hibernate sql ,and met problem.
I think its because ids is string.
How can I solve this?
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at org.hibernate.type.IntegerType.set(IntegerType.java:64)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:156)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:138)
at org.hibernate.param.PositionalParameterSpecification.bind(PositionalParameterSpecification.java:68)
at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:567)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1612)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2294)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2172)
at org.hibernate.loader.Loader.list(Loader.java:2167)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:448)...
Here is my code:
public List getUser(int leader, List<Member> members) {
String ids = String.valueOf(leader);
if (GeneralUtil.hasValue(members)) {
for (Member member : members) {
ids += "," + member.getUserId(); //1,2,3,4
}
}
try {
// Old method works well:
// StringBuffer qryStr = new StringBuffer(
// "from User u where u.userId in (" + ids + ")");
// return this.getHibernateTemplate().find(qryStr.toString());
StringBuffer qryStr = new StringBuffer("from User u where u.userId in (?)");
return this.getHibernateTemplate().find(qryStr.toString(), new Object[] { ids });
} catch (DataAccessException e) {
e.printStackTrace();
}
return null;
}
What about Integer array?
Integer[] ids = new Integer[members.size()+1];
ids[0] = leader;
for (int i = 0; i < members.size(); i++) {
ids[i+1] = member.getUserId();
}

Displaying data from an ISP/Telephone (Telstra.com.au in Australia)

I am currently having issues in attempting to display data (i.e. itemSummaries with a certain ContainerType) for sites that are ISP, as an example, www.telstra.com.au from Australia
Logging into the site works fine, and the credentials for the site work fine (in other words, it does a refresh which succeeds), however there doesn't appear to be a way to display the itemSummary data
The soap command getItemSummaries, doesn't display data for the item (it displays item data from financial institutions fine). Upon examining the sample code provided by Yodlee for the java soap api, you are meant to use the getItemSummaries1 along with setting ContainerTypes using a SummaryRequest
The problem is that this returns a CoreExceptionFaultMessage. The getItemSummaries1 command is causing the CoreExceptionFaultError. Using different ContainerTypes with different combinations (i.e. ISP, Telephone, Bills) didn't alleviate the issue
The same error message is returned in Yodlees own sample code, i.e. java_soap_example (run the com.yodlee.sampleapps.accountsummary.DisplayBillsData main method and provide the Yodlee login info as command line arguments)
As a reference, the code that is provided by Yodlee sample app is below
Running the getItemSummaries1 command
public void displayBillsData (UserContext userContext)
{
/*SummaryRequest sr = new SummaryRequest(
new String[] {ContainerTypes.BILL, ContainerTypes.TELEPHONE},
new DataExtent[] { DataExtent.getDataExtentForAllLevels(),DataExtent.getDataExtentForAllLevels() }
);*/
SummaryRequest sr = new SummaryRequest();
List list = new List();
list.setElements(new String[] {ContainerTypesHelper.BILL, ContainerTypesHelper.TELEPHONE});
sr.setContainerCriteria(list);
Object[] itemSummaries = null;
List itemSummariesList = null;
try {
itemSummariesList = dataService.getItemSummaries1(userContext, sr);
if (itemSummariesList != null){
itemSummaries = itemSummariesList.getElements();
}
} catch (StaleConversationCredentialsExceptionFault e) {
e.printStackTrace();
} catch (InvalidConversationCredentialsExceptionFault e) {
e.printStackTrace();
} catch (CoreExceptionFault e) {
e.printStackTrace();
} catch (IllegalArgumentTypeExceptionFault e) {
e.printStackTrace();
} catch (IllegalArgumentValueExceptionFault e) {
e.printStackTrace();
} catch (InvalidUserContextExceptionFault e) {
e.printStackTrace();
} catch (IllegalDataExtentExceptionFault e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
if (itemSummaries == null || itemSummaries.length == 0) {
System.out.println ("No bills data available");
return;
}
for (int i = 0; i < itemSummaries.length; i++) {
ItemSummary is = (ItemSummary) itemSummaries[i];
displayBillsDataForItem(is);
// Dump the BillsData Object
// dumpBillsDataForItem(is);
}
}
Printing the item data
public void displayBillsDataForItem (ItemSummary is)
{
String containerType = is.getContentServiceInfo ().
getContainerInfo ().getContainerName ();
System.out.println("containerType = " + containerType );
if (!(containerType.equals(ContainerTypesHelper.BILL ) || containerType.equals(ContainerTypesHelper.TELEPHONE)
|| containerType.equals(ContainerTypesHelper.MINUTES))) {
throw new RuntimeException ("displayBillsDataForItem called with " +
"invalid container type: " + containerType);
}
DisplayItemInfo displayItemInfo = new DisplayItemInfo ();
System.out.println("DisplayItemInfo:");
displayItemInfo.displayItemSummaryInfo (is);
System.out.println("");
ItemData id = is.getItemData();
if(id == null){
System.out.println("ItemData == null");
}else{
List accountsList = id.getAccounts();
Object[] accounts = null;
if (accountsList != null){
accounts = accountsList.getElements();
}
if (accounts == null || accounts.length == 0) {
System.out.println ("\tNo accounts");
}else {
for (int accts = 0; accts < accounts.length; accts++) {
BillsData billsData = (BillsData) accounts[accts];
System.out.println("\tAccount Holder: " + billsData.getAccountHolder() );
System.out.println("\tAccount Id: " + billsData.getAccountId());
System.out.println("\tItemAccountId: " + billsData.getItemAccountId() );
System.out.println("\tAccountName: " + billsData.getAccountName() );
System.out.println("\tAccountNumber: " + billsData.getAccountNumber() );
System.out.println("");
// Get List of Bill Objects
List billsList = billsData.getBills();
Object[] bills = null;
if (billsList != null){
bills = billsList.getElements();
}
if (bills == null || bills.length == 0) {
System.out.println ("\t\tNo Bill objects");
}else {
for (int b = 0; b < bills.length; b++) {
Bill bill = (Bill) bills[b];
System.out.println("\t\tBill Account Number: " + bill.getAccountNumber() );
System.out.println("\t\tBill Acct Type: " + bill.getAcctType() );
System.out.println("\t\tBill Due Date: " + Formatter.formatDate(bill.getDueDate().getDate(), Formatter.DATE_SHORT_FORMAT) );
System.out.println("\t\tBill Date: " + Formatter.formatDate(bill.getBillDate().getDate(), Formatter.DATE_SHORT_FORMAT) );
System.out.println("\t\tBill Past Due: "
+ (bill.getPastDue() != null ? bill
.getPastDue().getAmount() : 0.0));
System.out
.println("\t\tBill Last payment: "
+ (bill.getLastPayment() != null ? bill
.getLastPayment()
.getAmount()
: 0.0));
System.out.println("\t\tBill Amount Due: "
+ (bill.getAmountDue() != null ? bill
.getAmountDue().getAmount() : 0.0));
System.out
.println("\t\tBill Min Payment: "
+ (bill.getMinPayment() != null ? bill
.getMinPayment()
.getAmount()
: 0.0));
System.out.println("");
// Get List of AccountUsageData
List acctUsageDataList = bill.getAccountUsages();
Object[] acctUsageData = null;
if (acctUsageDataList != null){
acctUsageData = acctUsageDataList.getElements();
}
if (acctUsageData == null || acctUsageData.length == 0) {
System.out.println ("\t\t\tNo AccountUsageData objects");
}else {
for (int usage = 0; usage < acctUsageData.length; usage++) {
AccountUsageData aud = (AccountUsageData) acctUsageData[usage];
System.out.println("\t\t\tAccount Usage Bill ID: " + aud.getBillId() );
System.out.println("\t\t\tAccount Usage Units Used: " + aud.getUnitsUsed() );
}
}
}
}
System.out.println("");
// Get List of AccountUsageData
List acctUsageDataList = billsData.getAccountUsages();
Object[] acctUsageData = null;
if (acctUsageDataList != null){
acctUsageData = acctUsageDataList.getElements();
}
if (acctUsageData == null || acctUsageData.length == 0) {
System.out.println ("\t\tNo AccountUsageData objects");
}else {
for (int usageData = 0; usageData < acctUsageData.length; usageData++) {
AccountUsageData aud = (AccountUsageData) acctUsageData[usageData];
System.out.println("\t\tAccount Usage Bill ID: " + aud.getBillId() );
System.out.println("\t\tAccount Usage Units Used: " + aud.getUnitsUsed() );
}
}
}
}
}
}
EDIT2:
I have updated the getItemSummaries1 command to look like this
ContainerCriteria bills = new ContainerCriteria();
ContainerCriteria telephone = new ContainerCriteria();
ContainerCriteria isp = new ContainerCriteria();
ContainerCriteria utilities = new ContainerCriteria();
bills.setContainerType(ContainerTypesHelper.BILL);
telephone.setContainerType(ContainerTypesHelper.TELEPHONE);
isp.setContainerType(ContainerTypesHelper.ISP);
utilities.setContainerType(ContainerTypesHelper.UTILITIES);
Object[] containerList = {
bills,telephone,isp,utilities
};
SummaryRequest sr = new SummaryRequest();
List list = new List();
list.setElements(containerList);
sr.setContainerCriteria(list);
The command now executes and works correctly, however its returning a list of 0 elements (using DataExtents with different values didn't change anything). My suspicion is that Telstra.com.au site is broken on Yodlee's end (when a full refresh is done on the Telstra site, Yodlee returns a null for refreshing that specific site).
So far I can see some deviation, so do modify your container criteria as mentioned below
object[] list = {
new ContainerCriteria { containerType = "bills" },
new ContainerCriteria { containerType = "telephone" }
};
sr.containerCriteria = list;
You may additionally provide data extent as follows
DataExtent de = new DataExtent();
dataExtent.startLevel = 0; //as per your needs
dataExtent.endLevel = 0; //as per your needs
object[] list = {
new ContainerCriteria { containerType = "bills", dataExtent = de },
new ContainerCriteria { containerType = "telephone", dataExtent = de }
};
sr.containerCriteria = list;
This should solve your issue. If not then try to get the detail which is is node in the response for the CoreExceptionFaultMessage, this detail may help to diagnose the accurate issue.
To get data for any of the container first you need to add an account for the site belonging to that container. Once you have added the account successfully then only you will be able to pull in the data for such container. Also you can check the tag returned in the getItemSummaries API which has and once this statusCode = 0 then only you have data present for that account.
You can do testing by using the Dummy account which yodlee provides. Please refer to Yodlee Dummy account generator page for more info on Dummy accounts.

REFACTOR: Clean dao code for a query with multiple optional params

Is there a possiblity to clean up such a dao method?
I don't like the 2 if's for each param, but there isn't something like "query.setSql()" so i could update the sql after adding the params and building the sql.
public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) {
String sql = "FROM MyEntity e WHERE 1=1";
if(l1 != null){
sql += " AND e.link1 = :l1 ";
}
if(l2 != null){
sql += " AND e.link2 = :l2 ";
}
if(att != null){
sql += " AND e.attribute = :att ";
}
Query query = getEntityManager().createQuery(sql);
if(l1 != null){
query.setParameter("l1", l1);
}
if(l2 != null){
query.setParameter("l2", l2);
}
if(att != null){
query.setParameter("att", att);
}
return (List<MyEntity>)query.getResultList();
}
I store the parameters in a hashmap in the first if:
public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) {
String sql = "FROM MyEntity e WHERE 1=1";
HashMap parameters = new HashMap();
if(l1 != null){
sql += " AND e.link1 = :l1 ";
parameters.put("l1", l1);
}
if(l2 != null){
sql += " AND e.link2 = :l2 ";
parameters.put("l2", l2);
}
if(att != null){
sql += " AND e.attribute = :att ";
parameters.put("att", l1);
}
Query query = getEntityManager().createQuery(sql);
SQLUtility.setParameters(query, parameters);
SQLUtility.setParameters (easy to implement, write it yourself) loops over the HashMap keys and sets the parameters on the query.
I would suggest looking into visitor design pattrn.
You can create visitor that visits each of your parameter (which become visitable) and while doing so adds condition to your query string.
Maybe QueryDSL http://www.querydsl.com/ is something you can use to improve your SQL-related code?
When using QueryDSL your statements would be built using only one if per parameter (and your statements will be build statically typed without any string acrobatics) :
public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) {
QOriginLabel e = QOriginLabel.originLabel;
JPAQuery query = new JPAQuery(em).from(e);
if (l1 != null) {
query.where(e.link1.eq(l1));
}
if (l2 != null) {
query.where(e.link2.eq(l2));
}
if (att != null) {
query.where(e.attribute.eq(att));
}
return query.list(e);
}
If performance is not an issue, I like to code it like this:
public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) {
String sql = "FROM MyEntity e " +
" WHERE e.link1 = isnull(:l1, e.link1) " +
" AND e.link2 = isnull(:l2, e.link2)" +
" AND e.attribute = isnull(:att, e.attribute)";
Query query = getEntityManager().createQuery(sql);
query.setParameter("l1", l1);
query.setParameter("l2", l2);
query.setParameter("att", att);
return (List<MyEntity>)query.getResultList();
}

Categories