Mybatis resultmap ​only outputs one of three records - mybatis

I have 3 records to be populated from a medication table​:​
select * from ccda_medication where client_id = 100009;
client_id | rxcui | drug | medicationtime | status | directions |pharmacynote
-----------+--------+---------------------------------------+----------------+--------+------------------------------------+
100009 | 573621 | Albuterol 0.09 MG/ACTUAT [Proventil] | 20120806 | ACTIVE | 2 puffs every 6 hours PRN wheezing |
100009 | 866924 | Metoprolol Tartrate 25 MG Oral Tablet | 20120806 | ACTIVE | by mouth once daily|
100009 | 197517 | Clarithromycin 500 MG Oral Tablet | 20120806 | ACTIVE | by mouth twice daily for 7 days|
(3 rows)
The debug also shows that 3 records were retrieved from database.
==> Preparing: select * from ccda_medication where client_id = ?
==> Parameters: 100009(Integer)
<==Columns: client_id, rxcui, drug, medicationtime, status, directions, pharmacynote
<==Row: 100009, 573621, Albuterol 0.09 MG/ACTUAT [Proventil], 20120806, ACTIVE, 2 puffs every 6 hours PRN wheezing,
<==Row: 100009, 866924, Metoprolol Tartrate 25 MG Oral Tablet, 20120806, ACTIVE, by mouth once daily,
<==Row: 100009, 197517, Clarithromycin 500 MG Oral Tablet, 20120806, ACTIVE, by mouth twice daily for 7 days,
<== Total: 3
but I only g​e​t one record ​when I call selectMedications- the last one: Row: 100009, 197517
​Interestingly, if I ​flatten out Substance to contain all fields directly (no inner class), I get all 3 records, so the column names are correct.
The Mapper file is as the following:
<?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="ccda.mapper.interfaces.MedicationMapper">
<select id="**selectMedications**"
resultMap="MedicationsResultMap"
parameterType="Integer">
select * from ccda_medication where client_id = #{id}
</select>
<resultMap id="MedicationsResultMap" type="ccda.model.Substance">
<result property="status" column="status"/>
<association property="substanceTime" javaType="ccda.model.EffectiveTime">
<result property="low" column="medicationtime"/>
<result property="high" column="medicationtime"/>
</association>
<association property="medication" javaType="ccda.model.Medication">
<result property="rxcui" column="rxcui"/>
<result property="drug" column="drug"/>
<result property="directions" column="directions"/>
<result property="fillInstructions" column="pharmacynote"/>
</association>
</mapper>
The Substance, Medication and MedicationMapper are as the following:
package ccda.model;
public class Substance
{
public String status;
public EffectiveTime substanceTime;
public Medication medication;
}
package ccda.model;
public class Medication
{
public int rxcui;
public String drug;
public String directions;
public String fillInstructions;
}
package ccda.mapper.interfaces;
import java.util.List;
import ccda.model.Medication;
import ccda.model.Substance;
public interface MedicationMapper
{
List<Substance> selectMedications( int id );
}
​Can you please help me figure out why is that? Thanks A LOT!

The problem is that identifier field for substance is not specified. Because of this mybatis doesn't know what is the identity of returned entities and in this case it thinks that all records refer to the same entity.
So specify id in the resultMap and use unique field from ccda_medication for it.

Related

Parsing XML data with Postgres

PostgreSQL 9.2.4
I apologize if I added a duplicate topic, but I can't seem to figure it out (yet). I'd like to parse XML data which is stored in postgres table.
For example:
select program_information.description FROM program_information WHERE id = 8768787;
gives me output like:
<?xml version="1.0"?>
<ProgramInformation>
<BasicDescription>
<Title type="original">Zla smrt</Title>
<Synopsis length="short">Pet prijateljev, starih nekaj čez dvajset let, v samotni koči najde Knjigo mrtvih. S posnetka, ki so ga napravili arheologi, izvedo, da je bilo starodavno besedilo odkrito med kandarijskimi ruševinami sumerske civilizacije.</Synopsis>
<Keyword type="secondary"></Keyword>
<ParentalGuidance>
<mpeg7:ParentalRating href="rn:mpeg:MPAAParentalRatingCS:PG">
<mpeg7:Name>PG</mpeg7:Name>
</mpeg7:ParentalRating>
</ParentalGuidance>
<CreditsList>
<CreditsItem role="urn:tva:metadata:TVARoleCS:ACTOR">
<PersonName>
<mpeg7:GivenName>Bruce</mpeg7:GivenName>
<mpeg7:FamilyName>Campbell</mpeg7:FamilyName>
</PersonName>
</CreditsItem>
<CreditsItem role="urn:tva:metadata:TVARoleCS:ACTOR">
<PersonName>
<mpeg7:GivenName>Ellen</mpeg7:GivenName>
<mpeg7:FamilyName>Sandweiss</mpeg7:FamilyName>
</PersonName>
</CreditsItem>
<CreditsItem role="urn:tva:metadata:TVARoleCS:ACTOR">
<PersonName>
<mpeg7:GivenName>Betsy</mpeg7:GivenName>
<mpeg7:FamilyName>Baker</mpeg7:FamilyName>
</PersonName>
</CreditsItem>
<CreditsItem role="urn:tva:metadata:TVARoleCS:DIRECTOR">
<PersonName>
<mpeg7:GivenName>Sam</mpeg7:GivenName>
<mpeg7:FamilyName>Raimi</mpeg7:FamilyName>
</PersonName>
</CreditsItem>
</CreditsList>
<ReleaseInformation>
<ReleaseDate>
<Year>1981</Year>
</ReleaseDate>
</ReleaseInformation>
</BasicDescription>
<AVAttributes>
<AudioAttributes>
<NumOfChannels>2</NumOfChannels>
</AudioAttributes>
</AVAttributes>
</ProgramInformation>
So what I'd like is a parsed output of that output in separate columns (title, synopsis, ratings, actors, etc.)
So what I'd like is an output like
+----------+-------------+----------------+
| Title | Synopsis | ParentalRating |
+----------+-------------+----------------+
| my title | some descr | rating |
+----------+-------------+----------------+
I've tried with xpath but so far a dead end... :/
Can anyone guide me to correct query? Thank you!
M
Your XML document misses a namespace declaration. Is it supposed to be like that? I manually added a namespace at <ProgramInformation> and it worked ..
<ProgramInformation xmlns:mpeg7="http://mpeg7.io">
.. with the following query:
SELECT
XPATH('//BasicDescription/Title/text()', t.xml) AS title,
XPATH('//BasicDescription/Synopsis/text()', t.xml) AS synopsis,
XPATH('//mpeg7:ParentalRating/mpeg7:Name/text()', t.xml,ARRAY[ARRAY['mpeg7', 'http://mpeg4.io']]) AS parentalRating
FROM t;
title | synopsis | parentalrating
--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------
{"Zla smrt"} | {"Pet prijateljev, starih nekaj čez dvajset let, v samotni koči najde Knjigo mrtvih. S posnetka, ki so ga napravili arheologi, izvedo, da je bilo starodavno besedilo odkrito med kandarijskimi ruševinami sumerske civilizacije."} | {PG}
(1 Zeile)

NHibernate inserting wrong Id

I am using MVC razor 5
I'm making managment page to add SelectList values (like Car models)
I have values in my car models table:
--------------------------------------
Id | Name | Deleted
1 | BMW | False
2 | Audi | False
3 | Ford | False
4 | BMW5 | False
5 | SEAT | False
--------------------------------------
When i add new value id becomes 130++
I have noticed that my main class last records Id is 130.
And when I insert a record in car model class Id is the nextval(Id) of main class
But these two tables does not share same Controller or so...
All sessions are closed by transaction.Commit() so session closes.
What may be wrong?
Nhibernate class mapping:
<class name="web_nt.Models.Class.CarModel" table="car_model" schema="public">
<id name="Id" column="id" type="int">
<generator class="native" />
</id>
<property name="model_name" />
<property name="deleted" />
</class>
It was generator class fault.
To use postgres sequence I needed to specify it (NHibernate does not always catch it itself)
<generator class="sequence">
<param name="sequence">car_model_id_sequence</param>
</generator>

XQuery modify with variable

I have the follow XML
<root>
<business name="LM" id="1" total_pes="0">
</business>
<business name="KO" id="354" total_pes="0">
</business>
<business name="TUI" id="889" total_pes="0">
</business>
</root>
I want to update the total_pes attribute with a record count of other table tbl_logs:
id | log
1 | A
1 | A
1 | A
354 | A
354 | A
889 | A
My output XML would be this:
<root>
<business name="LM" id="1" total_pes="3">
</business>
<business name="KO" id="354" total_pes="2">
</business>
<business name="TUI" id="889" total_pes="1">
</business>
</root>
This is what I already done:
DECLARE #total_pes_new int
DECLARE #ID INT
SET #ID = (SELECT TOP 1 ID FROM #IDS)
WHILE #ID IS NOT NULL
BEGIN
set #total_pes_new = ( SELECT COUNT(A.PES) FROM TBL A
WHERE A.ID = #ID)
SET #XML.modify('replace value of (/root/business[#id=sql:variable("#ID")]/#total_pes)[1] with sql:variable("#total_pes_new")')
SET #ID = (SELECT TOP 1 ID FROM #IDS WHERE ID > #ID)
END
I will have problems with this loop. Can anyone help me to do a better solution?
Tks
If your XML is in an XML database, then you also have the option of using XQuery Update, see http://www.w3.org/TR/xquery-update-10/.

Group by in JPA

My Question is why the GROUP BY didn't show in the glassfish logs.
i added the following data below because someone wants to see it
public List<Message> listAllMessageBySender(String currentUserID) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnit");
EntityManager entityManager = emf.createEntityManager();
TypedQuery<Message> eq = entityManager.createQuery("SELECT m FROM Message m WHERE m.sendBy.userId = :userid GROUP BY m.sendTo.userId", Message.class);
eq.setParameter("userid", Integer.parseInt(currentUserID));
List<Message> message = eq.getResultList();
return message;
}
Glassfish 3.1.2.Logs
FINE: SELECT id, message, send_date, send_by, send_to FROM message WHERE (send_by = ?)
bind => [50]
Data:
User A : sendBy.userId = 50
User B : sendTo.userId = 44
User C : sendTo.userId = 43
id send_date send_by send_to message
1 2013-03-14 14:58:46 44 50 50 send message to 44
2 2013-03-14 14:58:46 50 44 reply from 44 to 50
3 2013-03-14 17:38:52 44 50 2nd reply to 50
6 2013-03-14 18:22:10 50 44 44 reply to 50
7 2013-03-14 18:22:10 50 43 new
in the query above is i want to list all the user sent from User A. it causes duplication because there is two send_to 44. the xhtml below shows :
<ui:repeat value="#{messageController.items}" var="messageItem">
<br />
<div onclick="loadMessage()">
<h:panelGroup layout="block" >
<p:graphicImage height="50" width="50" value="#{messageItem.sendTo.profilePicture}"/>
</h:panelGroup>
<h:panelGroup layout="block" style="width: 270px;">
<h:outputText value="#{messageItem.sendTo.registerName}"/>
<h:panelGroup layout="block" style="float:right;">
<h:outputText value="#{messageItem.sendDate}" >
<f:convertDateTime pattern="HH:mm"/>
</h:outputText>
</h:panelGroup>
</h:panelGroup>
</div>
<p:remoteCommand name="loadMessageBean" action="#{messageController.loadMessage(messageItem.id)}" /> </ui:repeat>
ERD
User Table Message Table
user_id message_id
register_name send_date
send_to ----> referenced by user_id User Table
send_by ----> referenced by user_id User Table
This request doesn't make sense. group by is used when the select clause contains at least one aggregation function (sum, avg, min, max, etc.). And all the other columns must appear in the group by clause.
So for example, the following query would make sense:
SELECT max(m.length), sender.userId from Message m
inner join m.sendBy sender
GROUP BY sender.userId
It would return, for each message sender, the length of its longest message.
Tell us, with example data, what you would like your query to return.
If you want to get all the distinct users whom user A sent a message to, the query should simply be
select distinct m.sendTo from Message m
where m.sendBy.userId = :userid

mybatis return result map with duplicate entry

I am using mybatis to retrieve data from DB, the data returned is containing duplicate entries.
Required result : Column Name , Value
Expected result is : column1 value A
But returned result is : COLUMN1 value A , column1 value A.
Hope able to clarify my doubt.
Can anybody tell me why it is happening?
<select id="getContentMap" resultType="map" parameterType="map">
select planId,location_qualifier from disclaimer_disclosure_content where
<choose>
<when test="plan_id != null">
plan_id = #{plan_id}
</when>
<when test="product_id != null">
product_id = #{product_id}
</when>
<otherwise>
issuer_id = #{issuer_id}
</otherwise>
</choose>
and effective_date >= #{effective_date}
and location_qualifier LIKE CONCAT('%' , #{location_qualifier} , '%')
</select>
The issue you are seeing is a bug in MyBatis 3 up until release 3.0.6: http://code.google.com/p/mybatis/issues/detail?id=303.
After that release you get the answer I outlined in my other answer (which was done with MyBatis 3.1.1).
You have four options:
Just ignore it and only grab the uppercase or lowercase entries
Upgrade to at least 3.0.6
Stop using map as resultType and move to a POJO domain object
Use the workaround below:
workaround for MyBatis < 3.0.6
Use full uppercase column aliases and they will only show up once (as uppercase) in your map:
<select id="getContentMap" resultType="map" parameterType="map">
select plan_id as PLAN_ID, location_qualifier as LOCATION_QUALIFIER from disclaimer_disclosure_content
where
<!-- SNIP: is the same as you had -->
</select>
This results in the output:
{PLAN_ID=2, LOCATION_QUALIFIER=Bar}
(or something similar depending on exactly how your select looks).
You will probably need to report more information, such as:
what database are you using?
what version of MyBatis 3 are you using (or are you still using iBATIS)?
what does your table structure look like?
In any case, I tried out a slightly simplified version of your query using MySQL 5.1 and MyBatis-3.1.1 and it worked fine - meaning that I only got back one entry of the column name in the result map. I provide my setup below so you can try to reproduce it or diagnose where your code may be wrong.
First, you have a error in your select statement. You have
SELECT planId
but then you have:
WHERE ... plan_id = #{plan_id}
so you probably meant SELECT plan_id in the SELECT clause.
Here is what worked for me.
My slightly simplified MyBatis select mapping is:
<select id="getContentMap" resultType="map" parameterType="map">
SELECT plan_id, location_qualifier FROM disclaimer_disclosure_content
WHERE
<choose>
<when test="plan_id != null">
plan_id = #{plan_id}
</when>
<otherwise>
product_id = #{product_id}
</otherwise>
</choose>
AND location_qualifier LIKE CONCAT('%' , #{location_qualifier} , '%')
</select>
Second, my MySQL table for this query:
mysql> select * from disclaimer_disclosure_content;
+---------+--------------------+------------+
| plan_id | location_qualifier | product_id |
+---------+--------------------+------------+
| 1 | Foo | 101 |
| 2 | Bar | 102 |
| 3 | Baz | 103 |
| 4 | Quux | 104 |
+---------+--------------------+------------+
4 rows in set (0.01 sec)
Third, my Java code to use the mapping:
#Test
public void testForSO() throws Exception {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("plan_id", 2);
paramMap.put("location_qualifier", "Ba");
List<Map<String,Object>> lmap = session.selectList("getContentMap", paramMap);
assertNotNull(lmap);
Map<String,Object> m = lmap.get(0);
assertNotNull(m);
System.out.println(m.toString());
}
This passes and prints out:
{location_qualifier=Bar, plan_id=2}
I also tried it with
Map<String,Object> m = session.selectOne("getContentMap", paramMap);
and get the same expected result.