JPA string comparison - string

I've written a simple login system using a JPQL query, which always returns no result:
public boolean check(String name, String password) {
final String qstring="SELECT e FROM Muser e WHERE e.name = '"+name+"'";
Muser user;
try{
user = em.createQuery(qstring, Muser.class).getSingleResult();
}
catch(NoResultException e){
return false;
}
return password.equals(user.getPassword());
}
When I changed it to a native query:
user = (Muser) em.createNativeQuery(qstring, Muser.class).getSingleResult();
or an int expression:
final String qstring="SELECT e FROM Muser e WHERE e.id = "+id;
It goes all right. What's the problem? Thanks a million!

It might be a problem with string comparison in your JPA provider. Do you test it on the case-sensitive data?
You could also try (and it's the preferred way) using parameters instead of crafting your statement by hand. It's not only safer (prevents SQL injection) but also faster: not only for Java (you don't concatenate Strings) but also for the DB (the query can be prepared once for all executions). It might be something like this:
final String qstring = "SELECT e FROM Muser e WHERE e.name = :name";
TypedQuery<Muser> query = em.createQuery(qstring, Muser.class);
query.setParameter("name", name);
user = query.getSingleResult();

I think problem is because of String comparison.My solution to this problem is:
using lowercase for comparison.
final String qstring = "SELECT e FROM Muser e WHERE LOWER(e.name) = :name";
TypedQuery<Muser> query = em.createQuery(qstring, Muser.class);
query.setParameter("name", name.toLowerCase());
user = query.getSingleResult();

Related

FlexibleSearch using enum in WHERE clause

I am working with Hybris and trying to query all the products that have an approval status of APPROVED within Java code. It should look like below, but I cannot get it to work in either HAC, or in Java code.
What is the correct way to do it?
SELECT {p:pk} FROM {Product as p join EnumerationValue as enum on enum.pk = p.approvalStatus } WHERE {enum:code[en]} = 'APPROVED'
Thank you everyone, here is the final answer that works, see comments in other replies for some more questions I have and hopefully some wonderfully wise replies:
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("SELECT {p:").append(ProductModel.PK).append("} ");
stringBuilder.append("FROM {").append(ProductModel._TYPECODE).append(" as p join ")
.append(ArticleApprovalStatus._TYPECODE).append(" as enum on {enum.pk} = {p.").append(ProductModel.APPROVALSTATUS).append("} join ")
.append(CatalogVersionModel._TYPECODE).append(" as cv on {cv.pk} = {p.").append(ProductModel.CATALOGVERSION).append("} } ");
stringBuilder.append("WHERE ( {enum:code} = ?approvalStatus1 or {enum:code} = ?approvalStatus2} and {cv:")
.append(CatalogVersionModel.VERSION)
.append("} = ?version");
final String unapprovedString = ArticleApprovalStatus.UNAPPROVED.toString().toLowerCase();
params.put("approvalStatus1", unapprovedString);
params.put("approvalStatus2", ArticleApprovalStatus.UNAPPROVED.toString().toLowerCase());
You need to use the type of the enum. Also, the enum code is case-sensitive; it depends on what is defined in the items.xml.
SELECT * FROM {Product
JOIN ArticleApprovalStatus ON {Product.approvalStatus} = {ArticleApprovalStatus.pk}}
WHERE {ArticleApprovalStatus.code} = 'approved'
Try to wrap the attributes with {} like this:
SELECT {p:pk} FROM {Product as p join EnumerationValue as enum on {enum.pk} = {p.approvalStatus} } WHERE {enum:code[en]} = 'APPROVED'

Saving a string found with .contains as a String variable?

First of all, I don't have any code to show yet, but the idea is that there is a text document that contains information, say... 'John Fitzgerald New York' on a single line, and I want to find that via .contains(), for example:
Scanner newScanner = new Scanner(inputFile);
String name = "Fitzgerald";
while(!newScanner.nextLine().contains(name)){
}
The idea being that I can then save the entire line as a variable. A search for Fitzgerald should allow me to save John Fitzgerald New York as a variable, in other words. Any ideas?
Scanner sc = new Scanner(new File("input.txt")); // Read from file
final String pattern = "Fitzgerald"
while( sc.hasNext() ){ // While you still have more data
String l = sc.next(); // Get the next token
if( l.contains(pattern) ){ // Check if it matches your pattern
System.out.println("Match Found");
}
}
This is how you would do it if you want to loop over the tokens. Alternatively, you can use the next(Pattern) method if you want to find more complex patterns.
For a text document, consider using a FileReader.
final String pattern = "Fitzgerald"
FileReader f = new FileReader(new File("input.txt"));
BufferedReader b = new BufferedReader(f);
String line;
while( (line=b.readLine()) != null ){
if(line.contains(pattern)){
doSomething(line);
}
}

how to retrieve multiple properties using #NameLookup in lotus notes

I am using #NameLookUp formula to retrieve internet address by giving a search key and it is working fine.But now i want to retrive not only the internet address but also some other properties like FirstName and LastName.
Here is the formula i am using to #Namelookup internet address by giving search string.
Vector vec=m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"InternetAddress\")");
//username is the String variable(Search Criteria)
Can anyone please help how to retrieve multiple properties(like firstName and lastName along with InternetAddress) by evaluate the formula only once. If it cant be done using #Namelookup is there any other way..?
This is a typical example when using evaluate() to call a Formula is not a good idea.
What you want to do is to get the NotesDocument class and read values from it.
Something like this (disclaimer, I am not a Java developer):
// Open Domino Directory on specified server
Database db = session.getDatabase("YourServer/Domain", "names.nsf");
// Get a view with user name is sorted first column
View view = db.getView("($Users)");
// Get the person document for specified user
Document doc = view.getDocumentByKey(userName, true);
if (doc != null) {
// Get text values from Notes document
String emailAddress = doc.getItemValueString("InternetAddress");
String officePhone = doc.getItemValueString("OfficeNumber");
String officeAddress = doc.getItemValueString("OfficeStreetAddress");
}
I believe this would be faster than multiple lookups using evaluate(), and you also have the added benefit of full error handling, and all being native code.
#NameLookup only returns the value of one item per call.
Assuming your goal is to only have one Evaluate statement, you could chain the calls together and return an array of values in a certain order:
Vector vec=m_session.evaluate("FirstName := #NameLookup([NoUpdate];\""+ userName + "\"; \"FirstName\"); LastName:= #NameLookup([NoUpdate];\""+ userName + "\"; \"LastName\"); InternetAddress :=#NameLookup([NoUpdate];\""+ userName + "\"; \"InternetAddress\"); FirstName:LastName:InternetAddress");
Or possibly:
String firstName = m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"FirstName\")");
String lastName = m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"LastName\")");
String internetAddress = m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"InternetAddress\")");
And then add those three strings in any order into your Vector.
Another approach is to use the DirectoryNavigator class. I believe it's been available since Notes/Domino 8.5 (perhaps even before that). DirectoryNavigator uses some of the same core logic as #NameLookup, so it should perform well.
Here's some sample code. I haven't tested this exact code, but I adapted it from production code that does a similar lookup:
String firstName = null;
String lastName = null;
String inetAddress = null;
Vector<String> lookupItems = new Vector<String>();
lookupItems.addElement("FirstName");
lookupItems.addElement("LastName");
lookupItems.addElement("InternetAddress");
Vector<String> vName = new Vector<String>();
vName.addElement(userName);
Directory dir = session.getDirectory();
DirectoryNavigator dirNav = dir.lookupNames("($Users)", vName, lookupItems, true);
if( dirNav != null && dirNav.getCurrentMatches() != 0 ) {
// Digest the results of the lookup
Vector<String> value = null;
value = dirNav.getFirstItemValue();
firstName = value.elementAt(0);
value = dirNav.getNextItemValue();
lastName = value.elementAt(0);
value = dirNav.getNextItemValue();
inetAddress = value.elementAt(0);
}

SubSonic How to Execute a SQL Statement?

My site is using Subsonic 2.2 on my site.
I have 1 weird situation where I need to run some ad-hoc SQL statements.
public IList<string> GetDistincList(string TableName, string FieldName)
{
string sqlToRun = string.Format("SELECT DISTINCT {0} FROM {1} ORDER BY {0}", FieldName, TableName);
Query query = new Query(TableName);
query.PleaseRunThis(sqlToRun);
query.ExecuteReader();
}
Can anyone help me here? As it appears, I just want to return a generic list of strings.
Thanks!
Subsonic has a great method called ExecuteTypedList() so you can do somethink like this.
List<int> result = DB.Select(Table.Columns.Id)
.Distinct()
.From<Table>()
.OrderBy(Table.Columns.Id)
.ExecuteTypedList<int>();
or even with pocos:
public class UserResult
{
public int Id {get;set;}
public string Name {get;set;}
}
List<UserResult> users = DB.Select(
User.Columns.UserId + " as Id", // the as ... is only needed if your
User.Columns.UserName + " as Name" // column name differs from the
).From<User>() // property name of your class
.ExecuteTypedList<UserResult>();
Unfortunately this method doesn't work for string since it requires
a) a valuetype
b) a class with a parameterless constructor since the method uses reflection to map the columns from the result to the properties of the class
However I wrote an extension method a while ago that works for string:
Use the Subsonic.Select() ExecuteTypedList Method with String
Look at my own answer in the link.
If you add the extensionmethod to your code you can do:
List<String> result = DB.Select(User.Columns.UserName)
.From<User>()
.ExecuteTypedList();
Use the CodingHorror class.
Here's the SubSonic 3 way of doing it: http://www.subsonicproject.com/docs/CodingHorror
The SubSonic 2 way is similar:
Dim ch As SubSonic.CodingHorror
ch.Execute("delete from #tablename", table)

Subsonic 3 - Sequence contains no matching element

I need help creating a LINQ SQL with subsonic. First the basics, this works fine:
var query = (from o in bd.concelhos
orderby o.descricao
select o);
var results = query.ToList<concelhos>();
However, I want to filter out some columns and I have created the following code:
var query = (from o in bd.concelhos
orderby o.descricao
select new FilteredConcelhos { id = o.idDistrito + "/" + o.idConcelho, descricao = o.descricao });
var results = query.ToList<FilteredConcelhos>();
which errors out in the ToList method with the description "Sequence contains no matching element"
Any help would be great with this...
update:
Turns out I was missing get set attributes in the newly declared class...
Like so
public class FilteredConcelhos
{
public string id { get; set; }
public string descricao { get; set; }
}
This clears the exception, but the resulting List is still all wrong (FilteredConcelhos.id contains nothing and FilteredConcelhos.descricao contains numbers)
Can you try to first execute the ToList and the select afterwards - then the select is performed via linq 2 objects!
Have you tried to work with an anonymous type?
var query = (from o in bd.concelhos
orderby o.descricao
select new { id = o.idDistrito + "/" + o.idConcelho,
descricao = o.descricao });
var results = query.ToList();
Unfortunately, this happened to me a lot. I'm not sure about the details of how Linq 2 Object works, but if you'll call ToList on the original object, like this:
from o in bd.concelhos.ToList()
...
It should do the trick.

Resources