Как динамически выбрать resultMap на основе значения столбца в MyBatis
У меня есть resultSet из БД, который возвращает две записи, как показано ниже
TRANID Type Name Amount
1 B ABC 100.00
1 S XYZ -100.00
Приведенные выше данные представляют собой транзакцию, в которой участвуют продавец и покупатель.
Теперь мне нужно сопоставить вышеуказанный набор результатов с MyBatis, чтобы он возвращал мне объект транзакции в структуре ниже.
Transaction :{
id : 1,
buyer:{
name : "ABC",
Amt : "100.00"
},
seller: {
name: "XYZ",
Amt: "-100.00"
}
}
Если БД возвратила данные в одной строке, а данные о покупателе и продавце в одном измерении, например
TRANID BNAME BAMOUNT SNAME SAMOUNT
1 ABC 100.00 XYZ -100.00
тогда я могу использовать карту результатов, как показано ниже
<resultMap id="transactionRM" type="Transaction">
<id property="id" column="TRANID"/>
<association property="buyer" type="User">
<result property="name" column="BNAME"/>
<result propert="amt" column="BAMT"/>
</association>
<association property="seller" type="User">
<result property="name" column="SNAME"/>
<result propert="amt" column="SAMT"/>
</association>
</resultMap>
Я смогу добиться того, чего хотел, потому что у меня есть уникальные псевдонимы / имена столбцов для покупателя и продавца.
Но как мне достичь тех же результатов, если результаты идут в два ряда, где один - это покупатель и продавец, а тип - это дискриминатор, который определяет, принадлежит ли строка продавцу или покупателю.
Я пытался определить карту результатов для пользователя, как
<resultMap id ="buyerRM" type ="User">
<result property="name" column="Name"/>
<result property="amt" column="Amount"/>
</resultMap>
<resultMap id ="sellerRM" type ="User">
<result property="name" column="Name"/>
<result property="amt" column="Amount"/>
</resultMap>
<resultMap id="transacionRM" type="Transaction">
<association property="buyer" resultMap="buyerRM" type="User"/>
<association property="seller" resultMap="sellerRM" type="User">
</resultMap>
Приведенная выше таблица результатов не будет работать, поскольку одинаковые имена столбцов, определенные как для покупателя, так и для продавца, и данные будут продублированы.
Какие-либо предложения.
Заранее спасибо.
2 ответа
Невозможно отобразить это в mybatis 3.4.6 без изменения запроса.
Если вы измените запрос, у вас есть несколько вариантов.
Автообъединение
Исходный запрос может быть преобразован для самостоятельного объединения по столбцу идентификатора транзакции. Таким образом, вы получите строку для каждой транзакции и сможете отобразить ее, как описано в вашем вопросе.
Переименование столбцов
Можно отобразить ассоциации, которые охватывают несколько строк. Данные объекта могут занимать несколько строк. Mybatis отображает данные строк в объекты, используя id
элемент отображения, то есть строки, которые имеют одинаковые id
значения принадлежат одному и тому же объекту, поэтому данные из них используются для заполнения созданного объекта (будь то подчиненный элемент, принадлежащий коллекции или ассоциации).
Если вы можете обернуть исходный запрос или изменить его напрямую, чтобы установить значения в разные столбцы в зависимости от типа, вы можете сделать это.
Под оберткой я подразумеваю что-то вроде:
select
TRANID,
case Type when 'S' then Name else null end as seller_name,
case Type when 'S' then Amount else null end as seller_amount,
case Type when 'B' then Name else null end as buyer_name,
case type when 'B' then Amount else null end as buyer_amount
from (
-- original query goes here
)
И отобразите это так:
<resultMap id ="userRM" type ="User">
<result property="name" column="name"/>
<result property="amount" column="amount"/>
</resultMap>
<resultMap type="Transaction" id="twoRowMap">
<id column="TRANID" property="id"/>
<association property="buyer" resultMap="userRM" columnPrefix="BUYER_"/>
<association property="seller" resultMap="userRM" columnPrefix="SELLER_"/>
</resultMap>
Обратите внимание, что из-за ошибки в mybatis вам необходимо указать columnPrefix
заглавными буквами в картографии.
Это выберет один Transaction
объект с правильно установленным buyer
а также seller
свойства.
Ассоциации работают только для отдельных строк. Самое близкое, что вы можете получить к тому, что вы хотите, с помощью коллекций.
<resultMap id="transactionRM" type="Transaction">
<id property="id" column="TRANID"/>
<collection property="users" type="User">
<result property="type" column="Type"/>
<result property="name" column="Name"/>
<result property="amt" column="Amount"/>
</collection>
</resultMap>
Это вернет один объект со свойством id
и собственность users
, Последний является List<User>
, что в данном конкретном случае будет иметь два элемента (по одному для каждой строки). Не совсем то, что вы хотите, но близко.
Вам нужно будет преобразовать это List<User>
на два отдельных свойства.