Where to add a separator for mybatis collections(List) - mybatis

Mapper.xml
<insert id="courseUploads" parameterType="com.technoshinelabs.eduskill.bean.Course" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into
course_uploads
(course_id, training_provider_logo, assignment_material, course_image, trainer_image, created_date, updated_date)
values(
#{courseId},
<foreach item="Course" collection="trainingProviderPath" >
#{Course}
</foreach>,
<foreach item="Course" collection="assignmentMaterialPath">
#{Course}
</foreach>,
#{courseImagePath},
<foreach item="Course" collection="trainerImagePath">
#{Course}
</foreach>,
now(), now()
)
</insert>
How do I add a separator for the above list(item="Course"), this list will have multiple data, each data needs to be separated by some separator, well the data needs to be stored in the database, please do help me on this.

You can use the separator attribute.
e.g.)
<foreach item="Course" collection="foo" separator="||">
#{Course}
</foreach>
Specifically, what of SQL do you want to generate?

Related

Mybatis When test condition with Internal query

I am looking for a query where i can use either internal query returned value or direct SQL in when test= in Mybatis.
<foreach item="ID"
index="index"
collection="selectionIds"
separator=";">
UPDATE TABLE_1 SET
ACT_IND ='N', upd_by = 1234
WHERE SLCT_ID = #{ID}
AND rem= select REM from TABLE_1 where SLCT_ID=#{ID}
<choose>
<when test="rem == 3">
AND Bbsid=#{nsid}
</when>
<otherwise>
AND asid=#{asid}
</otherwise>
</choose>
</foreach>
From the above query, how can i get the rem value and use in when condition.
Thanks

Postgres use xpath_table parsing with xmlnamespaces

Can I use xpath_table parsing with xmlnamespaces
drop table if exists _xml;
create temporary table _xml (fbf_xml_id serial,str_Xml xml);
insert into _xml(str_Xml)
select '<DataSet1 xmlns="http://tempuri.org/DataSet_LocalMaMC.xsd">
<Stations>
<ID>5</ID>
</Stations>
<Stations>
<ID>1</ID>
</Stations>
<Stations>
<ID>2</ID>
</Stations>
<Stations>
<ID>10</ID>
</Stations>
<Stations>
<ID/>
</Stations>
</DataSet1>' ;
drop table if exists _y;
create temporary table _y as
SELECT *
FROM xpath_table('FBF_xml_id','str_Xml','_xml',
'/DataSet1/Stations/ID',
'true') AS t(FBF_xml_id int,ID text);
select * from _y
If I take of the xmlnamespaces it works fine.
I thought to work with Xpath, but when there is null, it gives me wrong results.
With Postgres 10 or later, xmltable() is the preferred way to do this.
You can easily specify a list of namespaces with that.
SELECT fbf_xml_id, xt.id
FROM _xml
cross join
xmltable(xmlnamespaces ('http://tempuri.org/DataSet_LocalMaMC.xsd' as x),
'/x:DataSet1/x:Stations'
passing str_xml
columns
id text path 'x:ID') as xt
Note that in the XPath expression used for the xmltable() function, the tags are prefixed with the namespace alias defined in the xmlnamespaces option even though they are not prefixed in the input XML.
Online example

Collection size in mybatis query

I have a MyBatis query that looks like this:
<if test="userIdList != null and userIdList > 0">
AND galleries.id IN (
SELECT gallery_id
FROM gallery_users
WHERE gallery_id IN (
<foreach collection="userIdList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
)
GROUP BY gallery_id HAVING COUNT(gallery_id) = ???
)
</if>
That part I'm stuck on is getting the collection size which will be dynamic. So how can I get the collection size so that I can properly fill in the '???' value?
You can invoke the Collection#size() method using OGNL expression. i.e.
GROUP BY gallery_id HAVING COUNT(gallery_id) = ${userIdList.size}
Note that #{userIdList.size} won't work here because the expression in #{} is parsed by MyBatis' internal expression parser and not by OGNL.

using INSERT for an xml statement

how would you go about inserting an xml document of information into an existing table, I cannot figure out how the insert statement would work my code is below:
USE MyGuitarShop;
DECLARE #CustomerUpdate XML;
SET #CustomerUpdate = '
<NewCustomers>
<Customer LastName="Chan" FirstName="Isabella" Password="" EmailAddress="izzychan#yahoo.com"/>
<Customer LastName="Prine" FirstName="John" Password="" EmailAddress="johnprine#gmail.com"/>
<Customer LastName="Kitchen" FirstName="Kathy" Password="" EmailAddress="kathykitchen#sbcglobal.net"/>
</NewCustomers>
'
;
INSERT INTO Customers (LastName, Password, EmailAddress)
VALUES (#CustomerUpdate.value('(/NewCustomers/LastName)[1]', 'varchar(50)'),
(#CustomerUpdate.value('(/NewCustomers/FirstName)[1]', 'varchar(50)'),
(#CustomerUpdate.value('(/NewCustomers/Password)[1]', 'varchar(50)'),
(#CustomerUpdate.value('(/NewCustomers/EmailAddress)[1]', 'varchar(50)');
You're selecting the node LastName from NewCustomers, while NewCustomers contains only Customer nodes, which then contain LastName attribute.
In order to select the last name, use the following query instead:
value('(/NewCustomers/Customer/#LastName)[1]', 'varchar(50)')
Since you're extracting the data from a single XML value, the selection is pretty straightforward:
declare #CustomerUpdate xml;
set #CustomerUpdate = '
<NewCustomers>
<Customer LastName="Chan" FirstName="Isabella" Password="" EmailAddress="izzychan#yahoo.com"/>
<Customer LastName="Prine" FirstName="John" Password="" EmailAddress="johnprine#gmail.com"/>
<Customer LastName="Kitchen" FirstName="Kathy" Password="" EmailAddress="kathykitchen#sbcglobal.net"/>
</NewCustomers>';
select
t.Customer.value('#LastName', 'nvarchar(50)') as [LastName],
t.Customer.value('#FirstName', 'nvarchar(50)') as [FirstName],
t.Customer.value('#Password', 'nvarchar(50)') as [Password],
t.Customer.value('#EmailAddress', 'nvarchar(50)') as [EmailAddress]
from #CustomerUpdate.nodes('(/NewCustomers/Customer)') t(Customer)
If you were selecting the data from a row of XML values, you would have used cross apply instead.
Important note: DON'T STORE PASSWORDS IN PLAIN TEXT IN A DATABASE. If you're actually doing it, you do it wrong. If you don't understand why, learn about hash and salt, or, better, let others handle personal information for you: OpenID is one of the ways of moving the responsibility of securing sensitive data from you to Google-scale companies.

How to use SQL XML and XMLAGG to return multiple xmlelements

In SQL, I need to create xml code that looks like this:
<Phone>
<PhoneTypeCode tc="12">Mobile</PhoneTypeCode>
<Area>801</Area>
<DialNumber>9996666</DialNumber>
</Phone>
<Phone>
<PhoneTypeCode tc="2">Business</PhoneTypeCode>
<Area>801</Area>
<DialNumber>1113333</DialNumber>
</Phone>
using xmlagg, but it is throwing an error on the ',' after p.desc
How does this IBM DB2 SQL function need to be fixed to achieve the above xml?
select
xmlelement(Name "Phone",
xmlagg(xmlelement(name "PhoneTypeCode",
xmlattributes(trim(p.phtype) as "tc"), trim(p.desc)),
xmlelement(name "AreaCode", p.area),
xmlelement(name "DialNumber", p.phone)
)
) as xml
from phone p
where p.entityid = #entity_id
I also wanted to add that it does compile and run with this:
select
xmlelement(Name "Phone",
xmlagg(xmlelement(name "PhoneTypeCode",
xmlattributes(trim(p.phtype) as "tc"), trim(p.desc))
)
) as xml
from phone p
where p.entityid = #entity_id
Here is what it returns:
<Phone>
<PhoneTypeCode tc="12">Mobile</PhoneTypeCode>
<PhoneTypeCode tc="2">Business</PhoneTypeCode>
</Phone>
But of course, I need the Area and DialNumber. It is as if you can't have more than one xmlelement within an xmlagg.
How does this IBM DB2 SQL function need to be fixed to achieve the above xml?
Firstly, you may want to count your parentheses. Normally one would want as many closing parentheses as there are opening parentheses.
Secondly, you don't need XMLAGG() at all. You'd use it when inserting multiple elements of the same type, based on multiple relational records, into a single outer element, like
<phones>
<phone no="1" .../>
<phone no="2" .../>
...
</phones>
For you something like this should work:
with phone (phtype, desc, area, phone) as
(values ('home','blah','555','555-5555'),('office','blah','555','555-1111'))
select
xmlelement(
Name "Phone",
xmlelement(
name "PhoneTypeCode",
xmlattributes(
trim(p.phtype) as "tc"
),
trim(p.desc)
),
xmlelement(name "AreaCode", p.area),
xmlelement(name "DialNumber", p.phone)
) as xml
from phone p