one to many relation using mybatis or ibatis - ibatis

I have database which has two tables
post:
id
post_name
post_desc
files:
file_id
file_name
post_attachments
post_id
file_id
In my xml mapping I already have
<select id="selectPosts" resultType="com.mycom.myproject.bean.postBean">
select id, post_name as postName from post
</select>
So its a one to many realtionship. I want all the files attached to a post. I don't understand how I can do the mapping in mybatis.
I have my PostBean like
public class PostBean extends Post {
private List<FileAttachment> filesAttachment;
//getter setter
}
I am using mybatis with spring and mysql as database
Please let me know if you need anything else.
--update--
I have modified my mapper.xml as
<resultMap id="BaseResultMap" type="com.mycom.myproject.db.mybatis.model.post">
<!--
WARNING - #mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
This element was generated on Tue Sep 11 10:14:08 BST 2012.
-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="post_name" jdbcType="VARCHAR" property="postName" />
<collection property="filesAttachment" ofType="com.mycom.myproject.db.mybatis.model.FileAttachment">
<id property="fileId" column="file_id" />
<id property="fileName" column="file_name" />
</collection>
--- update2 ---
Actually I have one mapping table also which I have created above so my query is like
<select id="selectPosts" parameterType="string" resultType="com.mycom.myproject.bean.postBean">
select p.id, p.post_name, fa.file_id as fileId, fa.file_name as fileName from post p
left outer join files f on f.post_id = p.id join post_attachments pa on pa.file_id = f.post_id
where p.id = 371
</select>

As shown in the manual, you have to write a more complex query and change the mapper.
The request will be something like that :
<select id="selectPosts" resultType="com.mycom.myproject.bean.postBean">
select id, post_name, file_id, file_name as postName from post left outer join files
</select>
And your result map :
<resultMap id="detailedPostResultMap" type="Blog">
<result property="id" column="id"/>
<result property="name" column="post_name"/>
<collection property=filesAttachment" ofType="FileAttachment">
<id property="fileId" column="file_id"/>
<result property="fileName" column="file_name"/>
</collection>
</resultMap>

Related

Query XML value in sql

I need to get some information from XML in SQL Server 2008, but I cannot even get basic attribute from it. All samples that I tried failed. Table name is Item, xml column name is Data.
Simplified xml looks like this:
<AnchoredXml xmlns="urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008" SchemaWriteVersion="2">
<Key ScopeClass="Global">
<SchemaId Namespace="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008" ElementName="Topology" />
<AuthorityId Class="Host" InstanceId="00000000-0000-0000-0000-000000000000" />
</Key>
<Dictionary Count="1">
<Item>
<Key />
<Value Signature="a3502dd0-8c16-4023-9eea-30ea1c7a3a2b">
<Topology xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008">
<Services>
<Service RoleVersion="1" ServiceVersion="6" Type="Microsoft.Rtc.Management.Deploy.Internal.ServiceRoles.FileStoreService">
<ServiceId SiteId="1" RoleName="FileStore" Instance="1" />
<DependsOn />
<InstalledOn>
<ClusterId SiteId="1" Number="1" />
</InstalledOn>
<Ports xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008" />
<FileStoreService xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008" ShareName="lyncShare" />
</Service>
</Services>
</Topology>
</Value>
</Item>
</Dictionary>
</AnchoredXml>
I need to read information in AnchoredXml/Key/SchemaId/#NameSpace to select the right xml (there are more rows). Sample xml above is the right one. And after that I need to find the right service with
Type="Microsoft.Rtc.Management.Deploy.Internal.ServiceRoles.FileStoreService"
where is FileStoreService/#ShareName that I need.
I've tried to print the Namespace attributte for the start, but no sample code is working.
A few tries:
SELECT c.p.value('(#Namespace)[1]', 'varchar(50)') as 'Nmspace'
FROM Item
CROSS APPLY Data.nodes('/AnchoredXml/Key/SchemaId') c(p)
returns empty result set
SELECT Data.value('(/AnchoredXml/Key/SchemaId/#Namespace)[1]', 'varchar(50)')
FROM Item
returns NULL for all rows
SELECT
It.Data.exist('/AnchoredXml/Key/SchemaId[#Namespace="Microsoft.Rtc.Management.Deploy.Topology.2008"]')
FROM [xds].[dbo].[Item] AS It
returns 0's for all rows also without quotes ("")
A working sample code to get at least attribute test would be maybe sufficient and I would figure out the rest.
Could you please help me find errors in my queries or maybe identify some other problem?
Thanks
You're ignoring all the XML namespaces in your XML document! You need to pay attention to those and respect them!
There are XML namespaces on:
the root node <AnchoredXml>
(XML namespace: urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008)
the subnode <Topology>
(XML ns: urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008)
the subnode <FileStoreService>
(XML ns: urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008)
Try this:
-- respect the XML namespaces!!
;WITH XMLNAMESPACES(DEFAULT 'urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008',
'urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008' AS t,
'urn:schema:Microsoft.Rtc.Management.Deploy.ServiceRoles.2008' AS fss)
SELECT
ShareName = Data.value('(/AnchoredXml/Dictionary/Item/Value/t:Topology/t:Services/t:Service/fss:FileStoreService/#ShareName)[1]', 'varchar(50)')
FROM
dbo.Item
In my case, this returns:
ShareName
-----------
lyncShare

Solr DataImportHandler 1 to many relation

I have setup MySQL tables for storing articles.
Basically, they look like this:
article
-------
article_number
title
sets_article
-------
setcode
article_number
I have setup a schema.xml and configured the DataImportHandler. Everything works fine except, that the sets are not stored, when I call the DataImportHandler with full-import.
Here is my the relevant part of my data-config.xml:
<document name="articles">
<entity name="article"
pk="article_number"
query="select * from article"
deltaImportQuery="select * from article where article_number='${dih.delta.article_number}'"
deltaQuery="select article_number from article where tstamp > UNIX_TIMESTAMP(STR_TO_DATE('${dih.last_index_time}', '%Y-%m-%d %H:%i:%s'))">
<entity name="sets_article" query="select setcode as sets from sets_article where article_number='${article.article_number}'" />
<entity name="sets_articlel2" query="select distinct setcode as sets2 from sets_article" />
<entity name="sets_articlel3" query="select distinct setcode as sets3 from sets_article where article_number='11112222'" />
</entity>
</document>
The entities sets_article2 and sets_article3 work fine, so I think there is a problem with:
where article_number='${article.article_number}'
Does anybody know what is wrong with this setup?
The problem was a simple misconfiguration.
The tables didn't have the proper primary keys set.

Way to generically iterate through entities in XML?

Is there a generic way, in T-SQL, to iterate through an xml variable and get the xml for each entity in turn?
DECLARE #xml xml =
'<Entities>
<Entity key="4" attrib1="abc" attrib2="def" />
<Entity key="18" attrib1="ghi" attrib2="jkl" />
<Entity key="938" attrib1="mno" />
</Entities>'
For example, in the above XML, there are three instances of Entity. I want the XML for each one in turn. I can do this in a hard-coded way, e.g.
SELECT #entityxml = #xml.query('/Entities/Entity[1]')
which will return
<Entity key="4" attrib1="abc" attrib2="def" />
I can then change it to a [2] to get the next one, and so forth.
But, according to both BOL and experimentation, the parameter to #xml.query must be a string literal. In other words, a variable can't be used as the parameter, building it with [1], [2], etc., and getting however many entities there are. It appears we have hard-code the queries, which makes for some ugly code.
I know other methods can be used to get the data in the xml into a table, and then iterate through the rows in the table. I'm specifically asking about getting the XML itself, i.e. getting the equivalent of the above #xml.query, but being able to do so without having to hard-code the array value.
Thanks!
You can use position() to select elements based on index:
DECLARE #xml xml =
'<Entities>
<Entity key="4" attrib1="abc" attrib2="def" />
<Entity key="18" attrib1="ghi" attrib2="jkl" />
<Entity key="938" attrib1="mno" />
</Entities>'
declare #i int;
set #i = 2;
select #xml.query('Entities/Entity[position()=sql:variable("#i")]');
Something like this will do the trick:
DECLARE #xml xml =
'<Entities>
<Entity key="4" attrib1="abc" attrib2="def" />
<Entity key="18" attrib1="ghi" attrib2="jkl" />
<Entity key="938" attrib1="mno" />
</Entities>';
SELECT #xml.query('
for $i in //Entity
return
<Entity>
{ $i/#key }
{ $i/#attrib1 }
{ $i/#attrib2 }
</Entity>
');

solr: import from different datasources using DIH

I am trying to fill a Solr index from 2 different data-sources (xml and db) using the DataImportHandler.
1st try: Created 2 data-config.xml files, one for the xml import and one for the db import.
The db-config would read id and lets say field A. The xml-config also id and field B.
That works for both (i could import from both datasources), but the index got overwritten each time (with clean=false of course), so I either had id and A or id and B
so on for the
2nd try: merged the 2 files into one
<?xml version="1.0" encoding="UTF-8"?>
<dataConfig>
<dataSource
name="cr-db"
jndiName="xyz"
type="JdbcDataSource" />
<dataSource
name="cr-xml"
type="FileDataSource"
encoding="utf-8" />
<document name="doc">
<entity
dataSource="cr-xml"
name="f"
processor="FileListEntityProcessor"
baseDir="/path/to/xml"
filename="*.xml"
recursive="true"
rootEntity="false"
onError="skip">
<entity
name="xml-data"
dataSource="cr-xml"
processor="XPathEntityProcessor"
forEach="/root"
url="${f.fileAbsolutePath}"
transformer="DateFormatTransformer"
onError="skip">
<field column="id" xpath="/root/id" />
<field column="A" xpath="/root/a" />
</entity>
<entity
name="db-data"
dataSource="cr-db"
query="
SELECT
id, b
FROM
a_table
WHERE
id = '${f.file}'">
<field column="B" name="b" />
</entity>
</entity>
</document>
</dataConfig>
A bit funny is the id = '${f.file}'-part i guess, but that is the id that is used. The select statement is correctly formed, but I get an exception when trying to run that file in the dataimport.jsp. The first part (xml) works fine, but when he gets to the db part it raises:
java.lang.RuntimeException: java.io.FileNotFoundException:
Could not find file: SELECT id, b FROM a_table WHERE id = '12345678.xml'
at org.apache.solr.handler.dataimport.FileDataSource.getFile[..]
Any advice? Thanks in advance
EDIT
I found the problem for the FileNotFoundException: within the entity tags the datasource-attributes need to be camelCased --> dataSource..
Now it runs through, but with the same outcome as in the first try: only field B gets in the index. If I take the db-entity out, then the file contents are indexed (field A)
Try:
<entity name="db-data" dataSource="cr-db"
The attributes are case-sensitive, so your wrong-cased attribute name is ignored and you fall back to the default one (which somehow is the file one).

Solr data import multi-valued field into a single valued field

I have a multi-valued field
<arr name="colors">
<str>Blue</str>
<str>Red</str>
<str>Orange</str>
<str>Pink</str>
<str>Violet</str>
</arr>
Filled like this:
<entity name="pub_attributes" query=" SELECT name [description] FROM dbo.Colors">
<field name="colors" column="description" />
</entity>
And I need another field with all the colors but only in one line separated by white spaces like
<str name="Colors_All">Bue Red Orange Pink Violet</str>
How can I do this without accessing the Colors table all over again??
Maybe something like this
<entity name="Properites_all" query="
DECLARE #all VARCHAR(MAX)
SET #all = ''
Select #all = #all + ... from '${pub_attributes.colors}'
UNION
Another SELECT that will add more info than just the colors
">
<field name="colors_all" column="description" />
</entity>
I think, what you looking for is copyfield:
copyfield wiki and also you can take a look here:how to use it
Hope that will help.

Resources