I'm trying to copy rows with Oracle and myBatis with this statement:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
...
<insert id="copy" >
INSERT INTO ${table}
<foreach item="key" collection="keys" index="index" open="(" separator="," close=")">
${key}
</foreach>
VALUES
<foreach item="key" collection="map" index="index" open="(" separator="," close=")">
${key}
</foreach>
</insert>
</mapper>
--
for ( Map.Entry<Object, Object> entry2 : map.entrySet()) {
String key2 = (String) entry2.getKey();
Object value = null;
if (entry2.getValue() == null)
value = "NULL";
else if (entry2.getValue() instanceof java.sql.Timestamp)
{
//...
}
else if (entry2.getValue() instanceof Integer || entry2.getValue() instanceof Long ||
entry2.getValue() instanceof Short || entry2.getValue() instanceof java.math.BigDecimal
){
value = entry2.getValue();
}
else if (entry2.getValue().getClass().getName().equals("oracle.sql.CLOB"))
{
Clob clob=(Clob)entry2.getValue();
value= (String)clob.getSubString((long)1, (int)clob.length());
}
else{
value = "'" + entry2.getValue() + "'";
}
map.put(key2, value);
columans_valores.add("'" + key2 + "'");
}
copyService(map, map.keySet(), "table");
--
It works with most types, but CLOB and BLOB get their address copied instead or gets shrunk to 4000 bytes depending on the code i use to copy them, how do i deal with them?
Finally got it working with some tweaks:
To inform myBatis about the type used, switch $ for #
Avoid quotes
To prevent Oracle errors when inserting nulls, remove them from the map instead of
trying to insert null values
Related
I am a beginner in Spring MongoDB Criteria.
Once my database was mysql,if the variable is not none,I can do not none query like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mytest.modules.system.mapper.SysUserMapper">
<select id="getSysUser" resultType="org.mytest.modules.system.entity.SysUser">
select * from sys_user where del_flag = 0
<if test="username!=null and username!=''">
and username = #{username}
</if>
<if test="age!=null and age!=''">
and age = #{age}
</if>
<if test="profession!=null and profession!=''">
and profession = #{profession}
</if>
<if test="education!=null and education!=''">
and education = #{education}
</if>
<if test="dateStart!=null">
<![CDATA[ and DATE_FORMAT(time, '%Y-%m-%d %H:%T:%s') >=
DATE_FORMAT(#{dateStart} , '%Y-%m-%d %H:%T:%s') ]]>
</if>
<if test="dateEnd!=null">
<![CDATA[ and DATE_FORMAT(time, '%Y-%m-%d %H:%T:%s') <=
DATE_FORMAT(#{dateEnd} , '%Y-%m-%d %H:%T:%s') ]]>
</if>
</select>
</mapper>
Now my database change to mongoDB.How to do it with Criteria MongoTemplate with Criteria().andOperator?
SysUser sysUser = new SysUser();
// Create criteria object
Criteria criteria = Criteria.where("del_flag").is(0);
// Judge one by one
if (StringUtils.hasLength(sysUser.getUsername())) {
criteria = criteria.and("username").is(sysUser.getUsername());
}
if (Objects.nonNull(sysUser.getAge())) {
criteria = criteria.and("age").is(sysUser.getAge());
}
if (StringUtils.hasLength(sysUser.getProfession())) {
criteria = criteria.and("profession").is(sysUser.getProfession());
}
if (StringUtils.hasLength(sysUser.getEducation())) {
criteria = criteria.and("education").is(sysUser.getEducation());
}
if (Objects.nonNull(sysUser.getDateStart())) {
criteria = criteria.and("dateStart").gte(sysUser.getDateStart());
}
if (Objects.nonNull(sysUser.getDateEnd())) {
criteria = criteria.and("dateEnd").lte(sysUser.getDateEnd());
}
Query query = new Query(criteria);
List<SysUser> sysUserList = mongoTemplate.find(query, SysUser.class, "sys_user");
I am using Typehandler to map a List<Dep> to oracle array of ... here is the setPArameter method in the handler :
public void setParameter(PreparedStatement ps, int i, List<Dep> parameter, JdbcType jdbcType)
throws SQLException {
Connection connection = ps.getConnection();
// StructDescriptor structDescriptor = StructDescriptor.createDescriptor("MEMS_ARR", connection);
Struct[] structs = null;
if(parameter != null && parameter.size() >0) {
structs = new Struct[parameter.size()];
for (int index = 0; index < parameter.size(); index++)
{
Dep dep = parameter.get(index);
Object[] params = new Object[7];
params[0] = dep.getOrder();
params[1] = dep.getIdTp;
params[2] = dep.getId();
params[3] = " ";
params[4] = " ";
params[5] = " ";
params[6] = " ";
// STRUCT struct = new STRUCT(structDescriptor, ps.getConnection(), params);
structs[index] = connection.createStruct("MEMS", params);
}
// ArrayDescriptor desc = ArrayDescriptor.createDescriptor("MEMS_ARR", ps.getConnection());
// ARRAY oracleArray = new ARRAY(desc, ps.getConnection(), structs);
}else {
parameter = new ArrayList<DependentDTO>();
structs= new Struct[0];
}
this.parameter = parameter;
Array oracleArray = ((OracleConnection) connection).createOracleArray("MEMS_ARR", structs);
ps.setArray(i, oracleArray);
}
and here is the MEMS type :
create or replace TYPE MEMS AS OBJECT
( MEM1 NUMBER(2,0),
MEM2 VARCHAR2(1),
MEM3 VARCHAR2(15),
MEM4 VARCHAR2(60),
MEM5 VARCHAR2(1),
MEM6 VARCHAR2(40),
MEM7 VARCHAR2(10)
);
and here is the portion of the xml mapping file that uses the Typehandler :
#{nat,javaType=String,jdbcType=VARCHAR,mode=IN}, --nat
**#{deps,javaType=List,jdbcType=ARRAY,mode=IN,jdbcTypeName=MEMS_ARR,typeHandler=com.my.package.MyHandler}, --mems**
#{res,javaType=String,jdbcType=VARCHAR,mode=OUT} --res
the error log is as follows :
Error querying database. Cause: java.sql.SQLException: ORA-06550: line 31, column 5: PLS-00103: Encountered the symbol "" when expecting one of the following: . ( ) , * # % & = - + < / > at in is mod remainder not rem => <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec between || indicator multiset member submultiset The symbol "(" was substituted for "" to continue. ORA-06550: line 44, column 4: PLS-00103: Encountered the symbol ";" when expecting one of the following: . ( ) , * % & = - + < / > at in is mod remainder not rem => <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec between || multiset ### The error may exist in file [E:\path\to\mapper\ADao.xml] ### The error may involve my.package.ADao.mthodToCall -Inline ### The error occurred while setting parameters ### SQL: {call MY_PROC( ... , --nat?, **--mems? --res**)}
As you can see in the logs, the mems is replaced by empty string or is merged with the next arg res ... the comma is not there
Also kindly note that I already debugged inside the mybatis code and realized that the mapping setParameter method is called and the input List is mapped correctly to the oracle array ... the issue happens at the time of real calling
The issue actually was that I simply missed one comma between two previous parameters ... but the error pointed to the wrong parameter to look at
I have this problem. I need to execute selectKey to provide me with an id only when the supplied bookTypeId is null. Can it be done?
This is the insert function mapping:
<insert id="insert" parameterType="BookType">
<selectKey resultType="Integer" keyProperty="bookTypeId" order="BEFORE">
SELECT nextval('seq_book_type')
</selectKey>
INSERT INTO book_type(
book_type_id,
book_type_desc
)
VALUES(
#{bookTypeId},
#{bookTypeDesc}
)
</insert>
This is what I did after all:
<insert id="insert" parameterType="BookType">
<selectKey resultType="Integer" keyProperty="bookTypeId" order="BEFORE">
<if test="bookTypeId == null">SELECT nextval('seq_book_type')</if>
<if test="bookTypeId != null">SELECT #{bookTypeId}</if>
</selectKey>
INSERT INTO book_type(
book_type_id,
book_type_desc
)
VALUES(
#{bookTypeId},
#{bookTypeDesc}
)
</insert>
It works like a charm. Please anyone with myBatis experience, let me know if there is a better way than this.
I'm using:
PHPUnit 3.6.12 / PHP 5.3.1 / MySQL 5.1.30
I'm trying to compare the value inserted by a function in a database with the value I expect.
The value is a string CONTAINING ACCENTS.
So I created a xml file: expectedValue.xml (file encoded in UTF-8)
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<table name="MyTable">
<column>MyColumn</column>
<row>
<value>résumé</value>
</row>
</table>
</dataset>
Here is the code in the test method (file encoded in UTF-8 too)
public function testSave()
{
// this function saves the data in an UTF-8 database
save('résumé');
$queryTable = $this->getConnection()->createQueryTable('MyTable', 'SELECT MyColumn FROM MyTable') ;
$expectedTable = $this->createXMLDataSet('expectedValue.xml)->getTable('MyTable') ;
$this->assertTablesEqual($expectedTable, $queryTable) ;
}
And here is the result I get:
Failed asserting that
MYTable
MyColumn
résumé
is equal to expected
MyTable
MyColumn
résumé
Does anyone know where this encoding problem may come from ??
Thanks !!
Could possibly be the database connection
When you're connecting to MySQL (in your getConnection() method), you need to make sure you explicitly set UTF-8.
$pdo = new PDO(
'mysql:host=hostname;dbname=defaultDbName',
'username',
'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);
If you're not using MySQL, you can search for ways to set the charset.
I need a way to add an XML attribute 'POSITON' to an XML element 'node' conditionally. Currently I'm doing the condition check first and then creating the node.
if (lvl == 2)
node = <node COLOR={ color } CREATED={ epochTimeMillis } ID={ idGen } POSITION={ position } LINK={ link } MODIFIED={ epochTimeMillis } STYLE="bubble" TEXT={ f.getName() }>
<edge COLOR={ color } STYLE={ style } WIDTH={ width }/>
</node>
else
node = <node COLOR={ color } CREATED={ epochTimeMillis } ID={ idGen } LINK={ link } MODIFIED={ epochTimeMillis } STYLE="bubble" TEXT={ f.getName() }>
<edge COLOR={ color } STYLE={ style } WIDTH={ width }/>
</node>
}
Using "null" is not a good practice, but in this case it would help you:
scala> <root ta={ if (true) "true" else null } fa={ if (false) "false" else null } />
res0: scala.xml.Elem = <root ta="true" ></root>
A slightly cleaner way to do the same thing #senia suggests is:
val posOpt = if (lvl2) Some(myPosition) else None
val xml = <mydata position={posOpt orNull}/>
One way is to create the snippet before:
val pos =
if (lvl == 2) {
"position = ..."
} else {
""
}
and to always insert it in the result.
This could by extended by using an Option with embedded map in combination with string interpolation.
val pos =
if (lvl == 2) {
Some(position)
} else {
None
}
with
pos.map(v => s"position = $v")