Why mybatis need #Param? - mybatis

User selectUser(#param(“name”)String name,#param(“password”)String password);
<select id=" selectUser" resultMap="BaseResultMap">
select * from user where user_name = #{name} and user_password=#{password}
</select>
Like this code, mybatis can use reflection to get variable name, variables have different name, can replace #param(“XXX”).

To answer the actual question:
By default, the parameter names of methods are NOT part of the bytecode. So what you propose does not work by default.
MyBatis uses generic names for parameters for which it can't determine the name:
[...] they will be named by the literal "param" followed by their position in the parameter list by default, for example: #{param1}, #{param2} etc. If you wish to change the name of the parameters (multiple only), then you can use the #Param("paramName") annotation on the parameter.
So if you use those names in your SQL code things should work fine.
If you specify the -parameters compiler flag for javac it will indeed include the names of method parameters and the approach you suggested works in principle. I have seen a tutorial that claimed MyBatis will use those, although the reference documentation doesn't seem to mention it. You might give that a try.

Related

Access to Bind Parameters in MyBatis Interceptor

How do I read the bind parameters inside a MyBatis Interceptor? I'm trying to extract those information so I can write them to a log table.
The guide (http://www.mybatis.org/mybatis-3/configuration.html) didn't mention how to get them, and the JavaDoc (http://www.mybatis.org/mybatis-3/es/apidocs/org/apache/ibatis/mapping/BoundSql.html) does not have a single line of comment. I saw an example on SO about constructing a new BoundSql but that isn't what I needed.
I tried to test what contents are stored in BoundSql.getParameterMappings() and BoundSql.getParameterObject(), but it seems to be pretty complex. There's JavaType and JdbcType, and if there's only one parameter the ParameterObject isn't a Map object.
What is the proper way to get the bind parameters from BoundSql?
After going through MyBatis source code (where comment is an endangered species), I found out how MyBatis processes the bind parameters. However, that requires access to the JDBC Statement object, which is simply not available inside an Interceptor.
Then I did some testing and settled on this:
If there is only a single parameter, BindSql.getParameterObject() will give you the parameter itself. By using BindSql.getParameterMappings() and ParameterMapping.getJavaType() I can tell which Java class the parameter is.
If there are more than one parameter, BindSql.getParameterObject() will return an instance of org.apache.ibatis.binding.MapperMethod.ParamMap, which extends HashMap, or it will be an instance of the DTO you used. Using .getProperty() from ParameterMapping as key or as getter name, you can process the bind parameters one by one.
If anyone has a better way to do this, I'm all ears.

Inspecting Parameter Names from Annotation Processor

From ExecutableType we can inspect the types of parameters using getParameterTypes(). However, I cannot find a mechanism to inspect the parameter names.
I understand that in <= Java 7 the parameter names are not retained in the bytecode. However, I would still expect to be able to access the argument names arg0, arg1.
If the compiler is a Java 8 compiler running with the -parameters flag I would expect to get the original parameter names from the source code.
Is there a mechanism that I am overlooking? It seems strange that we are able to query this using the reflection API using Parameter.getName() if we are not capable of retrieving this information whilst annotation processing.
Instead of ExecutableType, use ExecutableElement. From this you can get it's parameters which should all have names. You can convert using Types.asElement.

what is the best way to specify default value for a date parameter in ireport

I have created a parameter in iReport Value_DT with Date data type.
If I'm using expression "new java.util.Date("01-SEP-14") as default value it works fine but this is hard code.
I'd like to use user defined function from Oracle DB, i.e. it might be similar to "new java.util.Date(new java.util.Date($F{GETACCOUNTINGDATE})) where GETACCOUNTINGDATE is oracle function.
With such syntax I have an error "The constructor Date(Timestamp) is undefined".
What should be changed in order to use function from DB in default parameter?
I'm not sure of any way to do this directly in the default value expression without writing custom code. I believe you would need to write a custom class with a static method which connects to your database, calls GETACCOUNTINGDATE, and returns the date. You could then, bundle this as a JAR, put it in your classpath and call this method in your Default Value Expression.
That's quite a bit of work though, so alternatively you may be able to 'recreate' the date using Java Date Function libraries.
We've used apache dateUtils:
org.apache.commons.lang.time.DateUtils.addMonths(new Date(),0))
I know a colleague has used jchronic to use strings and create dates.

does netbeans support naming conventions for fields, parameters and local variables like eclipse

eclipse supports naming conventions for fields, parameters and local variables. For each variable type it is possible to configure a list of prefix or suffix or both. eclipse respects this configuration when generating methods or getters/setters.
is there a similar configuration option in netbeans? is there another way to achieve the same thing: i want to get parameters with prefixes, when generating implementations for abstract methods and i want the prefix to be removed, when generating getters/setters (example: for _myVar it should generate getMyVar and setMyVar).
You can use Alt + Insert to generate some feature you need like getter and setter and constructors and ... . when you change something you can use re-factor.

Castle Windsor - Null constructor argument

How can I pass a null constuctor argument using Castle Windsor? I thought the following would work
<parameters>
<repository>null</repository>
<message>null</message>
</parameters>`
If you want them to be null, it means that they are non-essential dependencies. By having them as ctor arguments you suggest otherwise. You should redesign your class to have another constructor that takes only essential dependencies, if you wish that they not change throughout the lifetime of an object (be readonly), or expose them as properties.
With Windsor you can't make it to pass nulls, for reasons mentioned in the other answer.
Wouldn't it better to simply have an additional public constructor that doesn't take these parameters, then you wouldn't need to register the parameters in the config?
This was discussed a while back on the mail list, and at the time I looked into the code. Null values are deliberately filtered out (mainly because the complicate type resolution).
I couldn't find a simple way to make a special case to add them.