Using MyBatis (Version 3.2.5) I am trying to Update a DB2 DATE column with NULL, but getting this below error
org.springframework.jdbc.UncategorizedSQLException: Error setting null for parameter #5 with JdbcType NULL . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: com.ibm.db2.jcc.c.SqlException: [ibm][db2][jcc][10281][10295] JDBC type 0 is not yet supported.
; uncategorized SQLException for SQL []; SQL state [null]; error code [-99999]; [ibm][db2][jcc][10281][10295] JDBC type 0 is not yet supported.; nested exception is com.ibm.db2.jcc.c.SqlException: [ibm][db2][jcc][10281][10295] JDBC type 0 is not yet supported.
I tried the below suggestions, but they are not working for me
MyBatis - jdbcTypeForNull Oracle
The exception is thrown from line 39 of BaseTypeHandler.
Set a break point to check the current value of jdbcType.TYPE_CODE. It should work fine when it equals java.sql.Types.TIMESTAMP (93), that might not be the case.
So if not the case,
Expected actual type for this being DateTypeHandler.
You might then have to define your own DateTypeHandler, just extend it and override method setParameter from BaseTypeHandler, actually just replace variable jdbcType.TYPE_CODE with forced java.sql.Types.TIMESTAMP.
To use it by default for all Date parameters, register it in the typeHandler section of mybatis-config.xml (or Spring). Otherwise set the typeHandler attribute for concerned parameter in the insert statement.
Found the solution..
in mybatis-config.xml, I had
<setting name="jdbcTypeForNull" value="NULL" />
I changed it like below.
<configuration>
<settings>
<setting name="jdbcTypeForNull" value="DATE" />
</settings>
</configuration>
Related
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}
Trying to use the typehandler for an insert statement in mybatis, but it is not working. I am using mybatis-spring 1.2.1, mybatis 3.2.3. But I am getting an error message saying that parameter 2 is not set.
Here is the code,
mybatis config file:
<configuration>
<typeAliases>
.......
.........
<typeAlias type="org.test.util.TSTypeHandler" alias="TSTypeHandler"/>
</typeAliases>
<typeHandlers>
.......
<typeHandler handler="TSTypeHandler" javaType="java.lang.String" jdbcType="TIMESTAMP"/>
</typeHandlers>
<mappers>
......
</mappers>
</configuration>
Mapper xml:
<insert id="saveMyOutput">
INSERT INTO TEST.MY_OUTPUT (
YEAR,
RUN_TMS,
PRODUCT
)
VALUES
<foreach item="element" index="index" collection="mOutput"
open="(" separator="),(" close=")">
#{element.year},
#{element.runTS, typeHandler=TSTypeHandler},
#{element.product}
</foreach>
</insert>
Type handlers declared in mybatis config file are intended to be applied globally, then beware of side effect, especially when common types such are java.lang.String are involved.
In this case, mybatis would apply the type handler to every string to convert it to SQL timestamp. And I suppose you want most of string params be passed as is.
First, add logs in method TSTypeHandler.setNonNullParameter to check whether it is actually called or not.
Then just remove type handler from global config and reference it only in statement.
Try without alias first: use full qualified name.
Why do I get this error from MyBatis 3?
Caused by: java.sql.SQLSyntaxErrorException: unexpected token: < required: (
This is my SQL:
SELECT * FROM GC0101.AGENT_POOL_CLIENT_ASSIGNMENT WHERE GO_CD = ?
AND ASSIGNMENT_STATUS_CD IN %lt;foreach item="item" index="index"
collection="assignmentStatusCd" open="(" separator="," close=")"%gt;
? %lt;/foreach%gt;
created from this query:
#Select("SELECT * FROM GC0101.AGENT_POOL_CLIENT_ASSIGNMENT WHERE GO_CD =
#{generalOfficeCd, jdbcType=CHAR} AND ASSIGNMENT_STATUS_CD IN " +
"<foreach item=\"item\" index=\"index\" collection=\"assignmentStatusCd\"
open=\"(\" separator=\",\" close=\")\"%gt; #{item, jdbcType=CHAR} %lt;/foreach%gt;")
If that is indeed your annotation value then it will not work because you are trying to include an XML statement inside the annotation's only value which is not parsed for XML elements, it's taken "as it is".
You can find a possible solution in this post: How to use Annotations with iBatis (myBatis) for an IN query? (see the #Select("<script>...") example in LordOfThePigs' answer - works with the latest MyBatis version) or try with a #SelectProvider annotation. See the Mybatis 3 API docs for more details and this note as an advice:
Java Annotations are unfortunately limited in their expressiveness and flexibility. Despite a lot of time spent in investigation, design and trials, the most powerful MyBatis mappings simply cannot be built with Annotations – without getting ridiculous that is.
I am trying to build a simple website using an "ASP.NET Dynamic Data Entities Web Application" project template in VS 2012 (C#). It is pretty much the standard template setup, with an entity where DateTime type property is part of a primary key (the underlying table has also the SQL DateTime type on the mapped column). I get FormatException when I try to see the Details page, or edit a row:
String was not recognized as a valid DateTime. Description: An
unhandled exception occurred during the execution of the current web
request. Please review the stack trace for more information about the
error and where it originated in the code.
Exception Details: System.FormatException: String was not recognized
as a valid DateTime.
Source Error:
An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.
Stack Trace:
[FormatException: String was not recognized as a valid DateTime.]
System.Web.UI.WebControls.EntityDataSourceView.ExecuteSelect(DataSourceSelectArguments
arguments) +965
System.Web.UI.DataSourceView.Select(DataSourceSelectArguments
arguments, DataSourceViewSelectCallback callback) +21
System.Web.UI.WebControls.DataBoundControl.PerformSelect() +138
System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +30
System.Web.UI.WebControls.FormView.DataBind() +4
System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() +105
System.Web.UI.WebControls.FormView.EnsureDataBound() +178
System.Web.UI.WebControls.CompositeDataBoundControl.CreateChildControls()
+75 System.Web.UI.Control.EnsureChildControls() +83 System.Web.UI.Control.PreRenderRecursiveInternal() +42
System.Web.UI.Control.PreRenderRecursiveInternal() +168
System.Web.UI.Control.PreRenderRecursiveInternal() +168
System.Web.UI.Control.PreRenderRecursiveInternal() +168
System.Web.UI.Control.PreRenderRecursiveInternal() +168
System.Web.UI.Control.PreRenderRecursiveInternal() +168
System.Web.UI.Control.PreRenderRecursiveInternal() +168
System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
+974
I tried setting the culture in <globalization> node in web.config but it did not help.
The URL for Details page contains the columns in query string, looking like this: &Created=09%2F30%2F2013 16%3A10%3A33&Updated=09%2F30%2F2013 23%3A10%3A40 for a row where Created is '30-09-2013 16:10:33' and Updated '30-09-2013 23:10:40'.
It is my first Dynamic Data project so I do not really know what to do... Thanks in advance for any help.
Edit:
Adding
<globalization uiCulture="en-US" culture="en-US"/>
to system.web node of the main web.config caused the exception to disappear, but now the Details can't find the correct row, saying "No such item."
Since you have defined datetime as primary key, it is url-encoded by browser while sending get request. You should decode this value in your view before using it. Framework is trying to parse the encoded value as datetime and because of this giving exception.
You could be having localization issues, the datetime format can be different for different countries and also different between what you use in c# and sql
Try submitting in invariant format like yyyy-mm-dd
Also you should use datetimeoffset as your datetime instead, it has more precision and takes the same space if i remember correct, or at least use datetime2 as your sql data type since that has more precision and takes the same or less space.
Update:
It might be an issue with parsing the values as Adarsh suggests, you can change your culture programatically:
// Put the using statements at the beginning of the code module
using System.Threading;
using System.Globalization;
// Put the following code before InitializeComponent()
// Sets the culture to French (France)
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
// Sets the UI culture to French (France)
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
Taken from msdn
You can try that to see if that is perhaps the issue, then you can look into setting it from config or maybe look at different modelbinding for datetime, there are several solutions depending on what is right for you.
I managed to resolve the issue. Turns out the underlying table did not have primary key defined, so all the NOT NULL columns (including two DateTime columns) inferred Entity Key properties in the Entity Framework entity for that table. After setting "Entity Key" property to False for these two properties everything started to work as it should.
This is not a universal solution, but more of a workaround for this particular case, where rows are uniquely identified by other columns than those with DateTime type. If I really had a table where DateTime column would be the primary key, I guess I would run into the same issue again.
Regarding FormatException, setting <globalization culture="en-US" /> in web.config under system.web node fixed it, but after removing the Entity Key property from the DateTime columns even this was unnecessary, since DateTime values were not used to construct the URI anymore.
I have a stored procedure in SQL Sever 2008 like:
ALTER PROCEDURE [dbo].[mySP]
#FirstName As varchar(30),
#LastName As varchar(30),
#ID As int
As
Begin
--......
End
then in EF imported this SP as a function like:
public ObjectResult<Nullable<global::System.Int32>> MyFunc(global::System.String LastName, global::System.String FirstName,Nullable<global::System.Int32> ID)
{
//....
}
it works fine for long time.
Then I add some new thing to EF edmx with "update from database" today, the function parameter changed! it became:
public ObjectResult<Nullable<global::System.Int32>> MyFunc(global::System.String LastName,Nullable<global::System.Int32> ID, global::System.String FirstName)
{
//....
}
It's hardto believe it. I already have many codes to call this func and it worked fine. Now all of them are not working. Even I can manually change the parameter, but maybe it back the orginal order with the generated-code!
How to resolve this problem.
This error occurs when using ALTER PROCEDURE on the stored Procedure, and does not appear in all cases.
We have been able to show that the parameter order is controlled by SQL and that after altering a stored proc parameter list (e.g. adding a parameter, especially one with a default value), then using 'Update Model From Database' on the Entity model, the parameter order becomes alphabetical. One possibility is that SQL has a mechanism for maintaining compatibility with compiled procs when an optional parameter is added, and this is manifesting as the observed behavior.
You need to fix it in the database. The only way we have been able to restore the correct parameter order is to DROP and CREATE the stored procedure, then update the model. No change to the storage model will survive the Update from database.
We are using SQL 2000.
As of EF4, default code generation is also based on a T4 template. By drilling into that T4 we can see how it generate codes for the function import:
foreach (EdmFunction edmFunction in container.FunctionImports)
{
IEnumerable<FunctionImportParameter> parameters =
FunctionImportParameter.Create(edmFunction.Parameters, code, ef);
string paramList = string.Join(", ", parameters.Select(p =>
p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
...
So it's exactly based on how your SSDL schema is look like under you model.
For example, for the uspUpdateEmployeePersonalInfo SP in Adventureworks database:
CREATE PROCEDURE [HumanResources].[uspUpdateEmployeeHireInfo]
#EmployeeID [int],
#Title [nvarchar](50),
#HireDate [datetime],
#RateChangeDate [datetime],
#Rate [money],
#PayFrequency [tinyint],
#CurrentFlag [dbo].[Flag]
The SSDL is like the below:
<Function Name="uspUpdateEmployeePersonalInfo" Aggregate="false"
BuiltIn="false" NiladicFunction="false" IsComposable="false"
ParameterTypeSemantics="AllowImplicitConversion" Schema="HumanResources">
<Parameter Name="EmployeeID" Type="int" Mode="In" />
<Parameter Name="NationalIDNumber" Type="nvarchar" Mode="In" />
<Parameter Name="BirthDate" Type="datetime" Mode="In" />
<Parameter Name="MaritalStatus" Type="nchar" Mode="In" />
<Parameter Name="Gender" Type="nchar" Mode="In" />
</Function>
And it will result in this code to be generated inside the ObjectContext:
public int UpdateEmployeePersonalInfo(Nullable<global::System.Int32> employeeID,
global::System.String nationalIDNumber,
Nullable<global::System.DateTime> birthDate,
global::System.String maritalStatus,
global::System.String gender)
My guess is that the order of the properties in your SSDL schema in your model has been changed and EF generates new codes to match that. So after validating that the parameters are declared in the desired order in you SP inside the database, try removing the SP from you model and update your model from database one more time and you'll see that the generated method code will be changed accordingly.
We are seeing this issue happen with lots of our stored procedure and we have not been able to identify why. Any new information on this will be a lot of help.
I have seen it happen on stored procedure with a lot of input and output parameters more consistently. Moreover on update form database command which when stored procedure is not changed and also edmx file is not changed but the designer causes the reorder of parameters.
Verify that the compatibility level of the database is not below 90
sp_dbcmptlevel 'your_database_name'
If it reports a value below 90 then run
sp_dbcmptlevel 'your_database_name', 90
Thanks to lajones in Codeplex