How to implement <isEmpty> easily in mybatis? - mybatis

In ibatis2.X it used to be:
<isEmpty property="userName" >
In MyBatis now it is something like:
<if test="userName != null && userName.trim().length !=0 " >
I would like to find an easy alternative to isEmpty in MyBatis. I found I can also use this construct:
<if test="#org.apache.commons.StringUtils#isEmpty(userName)" >
But it is not very convenient either.
Maybe I am missing something and there is <isEmpty> in MyBatis, or even something like <if test="isEmpty(userName)" > would be good enough. Could you advice?

Related

When to use $ vs #?

I am confused about using $ vs #. I didn't found any guides for this. I used them as
name = #{name}, name like '%${word}%', order by name ${orderAs},where name = #{word}
Sometimes , these are work fine but at the sometimes , parameters aren't included or gave me error like
org.apache.ibatis.reflection.ReflectionException: There is no getter
for property named 'name'.......
So, I'd like to know when to use $ or # ?
Following the myBatis guidelines #{} is used in your sql statements.
If you take a look any of MyBatis Reference in the Section Mapper XML Files it says explicity:
Notice the parameter notation:
#{id}
Otherwise ${} is for
1- Configuration properties.
For example:
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
Then the properties can be used like next:
<dataSource type="POOLED">
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
2- String Substitution ${} (Parameters section):
By default, using the #{} syntax will cause MyBatis to generate
PreparedStatement properties and set the values safely against the
PreparedStatement parameters (e.g. ?). While this is safer, faster and
almost always preferred, sometimes you just want to directly inject a
string unmodified into the SQL Statement. For example, for ORDER BY,
you might use something like this:
ORDER BY ${columnName}
Here MyBatis won't modify or escape the string.
NOTE It's not safe to accept input from a user and supply it to a
statement unmodified in this way. This leads to potential SQL
Injection attacks and therefore you should either disallow user input
in these fields, or always perform your own escapes and checks.
So definitively in name like '%${word}%' ororder by name ${orderAs}` you need to use String substitution not a prepared statement.
This (${} - simple variable)
SELECT * from user where usernum = ${usernum}
translates into this
SELECT * from user where usernum = 666
, but this (#{} - equivalent to PreparedStatement in JDBC)
SELECT * from user where usernum = #{usernum}
translates into
SELECT * from user where usernum = ?
, so the best usage would be something like
SELECT * from ${tablename} where name = #{name}
I was also confused with this . Then I did some research. I had a query which is something like select * from tablename h where h.id=#userid# in ibatis. Then I had to migrate it into mybatis 3 . The same statement didnt work. So I had changed it into select * from tablename h where h.id=#{userid}

LINQ query where string does not contain a number

New to LINQ and I'm having trouble coming up with a simpler way to add a condition to exclude fields that contain numbers.
So far I've come up with:
db.MyDB.Where(x => !x.MyField.Contains('1') && !x.MyField.Contains('2') && !x.MyField.Contains('3') &&... etc.
There must be a better way to achieve this. I'm using entity framework.
Try something like this:
db.MyDB.Where(x => !x.MyField.Any(x => Char.IsDigit(x)))
You could also consider using a regex with \d.
There are a number of solutions, I suppose it comes down to what works best with whatever MyDB is in this scenario. You could make it more sql friendly by playing with SqlMethods
db.MyDB.Where(x => !SqlMethods.Like(x.MyField, "[0-9]"))
If this is linq to sql, use SqlMethods.Like
db.MyDB.Where(x => SqlMethods.Like(x.MyField, "%[0-9]%");
[edit] Well, it's not L2S, it's EF. I believe EF supports PatIndex
db.MyDB.Where(x => SqlFunctions.PatIndex("%[0-9]%", x.MyField) > 0);
(PATINDEX is 1-based, not 0 based)

drools rule for fact with list values and multiple conditions

i am attempting to write a rule that will compare a fact list values to a multiple condition rule
rule: only valid legislations
when
fact:Fact (legislationList == ('L1' && 'L2') OR 'L3')
then
fact.printMessage();
end
ie. if fact.legislationList={'L1', 'L2') then fire
if fact.legislationList={'L1', 'L4') then dont fire
i looked at the 'from' clause but wasnt clear how that would solve my issue.
is there some voodoo method/solution that will help me?
thanks
-lp
Assuming that legislationList is a List<String>, then you could use Drools' 'contains' operator:
rule: only valid legislations
when
fact:Fact ((legislationList contains "L1" && legislationList contains "L2") || legislationList contains "L3" )
then
fact.printMessage();
end
You can abbreviate the syntax a bit, but I wanted to be explicit.
Hope it helps,

Reuse of conditions (when) in Drool DSL statements

Is it possible to reuse a when/condition statement into another when/condition statement in a DSL file?
For example, I have two conditions:
[condition][]The client is invalid = Client( name == null || email == null )
[condition][]All the clients are invalid = forall( Client( name == null || email == null ) )
Note that the second condition just diff the first for the forall command, but the statement inside is equals. In these case, I want to reuse the first condition into the second.
Is it possible? How?
Thank you.
even the most recent version of drools will only let you substitute values into a template from pojo's or a corresponding map as per their documentation here.
This won't work for your use case though.
Since drool files are simply text files, there is nothing preventing you from considering a more powerful templating toolkit.
Possibilities include Apache Velocity, ANTLR or Scala!

Binding multiple variables in Drools LHS throws NPE

I have searched but can't find why this simple code will fail in Drools (core 5.2.1.Final and compiler 5.2.0.Final).
rule "name"
no-loop true
when
$offer: Offer(properties != null && properties.size() > 0, $properties : properties)
$invalidProperty: ContextualizedOfferProperty(name == null || "".equals(name)) from $properties
then
...
end
I get the following exception:
java.lang.NullPointerException
at org.drools.reteoo.FromNode.<init>(FromNode.java:87)
at org.drools.reteoo.builder.FromBuilder.build(FromBuilder.java:41)
at org.drools.reteoo.builder.PatternBuilder.attachPattern(PatternBuilder.java:122)
at org.drools.reteoo.builder.PatternBuilder.build(PatternBuilder.java:76)
at org.drools.reteoo.builder.GroupElementBuilder$AndBuilder.build(GroupElementBuilder.java:126)
at org.drools.reteoo.builder.GroupElementBuilder.build(GroupElementBuilder.java:73)
at org.drools.reteoo.builder.ReteooRuleBuilder.addSubRule(ReteooRuleBuilder.java:152)
at org.drools.reteoo.builder.ReteooRuleBuilder.addRule(ReteooRuleBuilder.java:123)
at org.drools.reteoo.ReteooBuilder.addRule(ReteooBuilder.java:110)
at org.drools.reteoo.ReteooRuleBase.addRule(ReteooRuleBase.java:419)
at org.drools.common.AbstractRuleBase.addRule(AbstractRuleBase.java:814)
at org.drools.common.AbstractRuleBase.addPackages(AbstractRuleBase.java:555)
at org.drools.reteoo.ReteooRuleBase.addPackages(ReteooRuleBase.java:436)
at org.drools.impl.KnowledgeBaseImpl.addKnowledgePackages(KnowledgeBaseImpl.java:149
If I remove the second binding, it passes correctly. I have tried many different, simple bindings, it always throws if I have two bindings, one referencing the other...
Basically, I want the rule to fire for each ContextualizedOfferProperty that has no name for any Offer having at least one property.
Any idea?
Thanks,
John
It looks like a bug. Have you tried version 5.3.1? It fixes several compilation problems like this.