How to use kotlin value classes with MyBatis - kotlin

Can anybody give advive for using kotlin inline class () with MyBatis.
I have this code:
MyBatis mapper:
#Mapper
interface EntityMapper {
fun findEntitiesByStatuses(startId: Long, fetchLimit: FetchLimit, statuses: List<String>)
}
Value class:
#JvmInline
value class FetchLimit(
val value: Int
) {
init {
require(value >= 1) {
"FetchLimit should be grater or equal 1. Current: $value"
}
}
}
Xml with sql:
<select id="findEntitiesByStatuses" resultMap="entitySelectionResultMap">
SELECT
e.id,
e.status,
e.created_datetime
FROM entity e
WHERE e.status IN
<foreach item="s" collection="statuses" separator="," open="(" close=")">
#{s}::public.offer_status
</foreach>
AND e.id >= #{startId}
ORDER BY e.id
LIMIT #{fetchLimit}
</select>
<resultMap id="entitySelectionResultMap" type="model.Entity">
<constructor>
<arg column="id" name="id"/>
<arg column="status" name="status"/>
<arg column="create_datetime" name="createDateTime"/>
</constructor>
</resultMap>
When i call mapper's method i get erorr:
Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): .....postgres.mybatis.mapper.EntityMapper.findEntitiesByStatuses-4Zcmpl0
But if i use data class or just Int it works fine.
Can anybody give adives how to use kotlin value class with myBatis?

Related

How to check parameter existance in myBatis mapper XML?

I simplifed my problem as following code.
Mapper Interface looks like:
#Mapper
public interface TestMapper {
public Integer countTable(#Param("tValue1") Integer tValue1);
public Integer maxTable(#Param("tValue2") Integer tValue2);
}
Mapper Xml looks like:
<sql id="sql_where">
<where>
<if test="tValue1 != null">tValue1 = #{tValue1}</if>
<if test="tValue2 != null">AND tValue2 = #{tValue2}</if>
<where>
</sql>
<select id="countTable" resultType="Integer">
SELECT COUNT(*) FROM TestTable
<include refId="sql_where"/>
</select>
<select id="maxTable" resultType="Integer">
SELECT MAX(*) FROM TestTable
<include refId="sql_where"/>
</select>
when countTable or maxTable method is called, BindingException occurs.
Due to one of parameter is not found.
How can I check the parameter exists in XML?
I could've insert all params to method, but I don't want programmers to be confused (they're not going to be used)

I encounter NoSuchMethodException myclass<init>() in mapper file for myBatis

I am trying to embed myBatis database structure to my existing project. I have already implemented it as an example. When I try to use same methods on my project, I am getting this NoSuchMethodException.
(by the way, this sql query works, I have already tried it on database with same values)
My class file
public class Cashflow {
public long id;
public LocalDate finalMaturityDate;
public int branchCode;
public int currencyCode;
public long rateProfileCodeId;
public Cashflow(long id, LocalDate finalMaturityDate) {
this.id = id;
this.finalMaturityDate = finalMaturityDate;
}
public Cashflow(long id, int branchCode, int currencyCode, long rateProfileCodeId){
this.id = id;
this.branchCode = branchCode;
this.currencyCode = currencyCode;
this.rateProfileCodeId = rateProfileCodeId;
this.finalMaturityDate = LocalDate.parse("2012-05-12");
}
public void setRateProfileCodeId(long rateProfileCodeId) {
this.rateProfileCodeId = rateProfileCodeId;
}
}
My mapper file:
<resultMap type="Cashflow" id="CashflowResult">
<result property="id" column="NAK_ID" />
<result property="branchCode" column="NAK_GIR_SUBE_KODU" />
<result property="currencyCode" column="NAK_DOVIZ_KODU" />
<result property="rateProfileCodeId" column="NAK_OPK_ID" />
</resultMap>
<select id="retrieveCashflowMyBatis" parameterType="long" resultMap="CashflowResult" >
SELECT
NAK_ID,
NAK_DOVIZ_KODU,
NAK_OPK_ID,
NAK_URN_ID,
NAK_GIRIS_TIP,
NAK_AKIS_TUTAR,
NAK_GIR_SUBE_KODU,
NAK_REFERANS_NO,
NAK_GECERLILIK_TARIH,
NAK_DURUM_KODU,
NAK_DETAY_GUNCELLEME,
MUI_MUSTERI_NO,
NAH_ODEME_BAS_TARIH,
NAH_ORTALAMA_VADE_TARIH,
NAH_ORTALAMA_VADE,
NAH_HESAPLAMA_TARIH,
NAH_DURASYON,
NAH_IRR,
NAH_FAIZ_HESAP_TIPI,
NAH_DURASYON_BAZ_TARIH,
NAH_KALAN_ORTALAMA_VADE,
NAH_FAIZ_TIPI,
OPK_LIBOR_BASAMAK_SAYISI,
OPK_ORAN_GUN_KODU,
OPK_GERI_ODEME_VALOR
FROM SCNAU.NAU_NAKIT_AKIS
LEFT OUTER JOIN
SCNAU.NAU_NAKIT_AKIS_HESAP
ON NAK_ID = 35
AND NAH_NAK_ID = NAK_ID,
SCNAU.NAU_MUSTERI_ILISKI,
SCNAU.NAU_ORAN_PROFIL_KOD
WHERE NAK_ID = 35
AND MUI_NAK_REFERANS_NO = NAK_REFERANS_NO
AND MUI_DURUM_KODU = '1'
AND NAK_OPK_ID = OPK_ID
WITH UR
</select>
My interface class for method:
public interface DatabaseService {
public Cashflow retrieveCashflowMyBatis(long cashflowId);
}
Your resultMap is trying to call the default constructor Cashflow() (because you didn't tell it to do something else), which doesn't exist. Either add one...
public Cashflow() {}
...or put the correct contructor parameters into your resultMap:
<resultMap type="Cashflow" id="CashflowResult">
<constructor>
<idArg column="NAK_ID" javaType="int"/>
<arg column=".." javaType=/>
<!-- do for all constructor arguments branchCode, currencyCode, rateProfileCodeId -->
</constructor>
... result tags as needed
</resultMap>

ibatis TypeHandlerCallback for multi column mapping - Money object

Ibatis multi column datamapping to type handler.
I have a money object I am using which needs value and currency.
How to map multiple columns to same callbacktype handler?
Java Money object
http://www.javapractices.com/topic/TopicAction.do?Id=13
public class MoneyTypeHandlerCallBack implements TypeHandlerCallback {
//The below works but problems it always defaults currency. I need to be able to get Currency as well to use
// new Money(value, currency ) constructor
#Override
public Object getResult(final ResultGetter getter) throws SQLException {
BigDecimal value = getter.getBigDecimal();
if (value == null) {
return null;
}
Money result = new Money(value); // I need to be able to do new Money (value, currency)
return result;
}
... implment other...
}
SomeView Bean definition:
public class SomeView implements Serializable{
private String companyName
private Money netamount;
// .....geters and setters etc
}
SQLMAP Configurations:
<sqlMap namespace="myspace">
<typeAlias alias="someView" type="com.my.view.someView" />
<resultMap id="some_detail_view" class="someView">
<result property="companyName" column="COMPANY" />
...
<result property="netamount" column="NET_AMT" />
<result property="netamountCurrency" column="NET_AMT_CURRENCY" />
</resultMap>
<select id="someView" parameterClass="java.util.Map"
resultClass="someView" resultMap="some_detail_view">
SELECT COMPANY, NET_AMT, NET_AMT_CURRENCY From......
</select>
</sqlMap>

HiLo NHibernate id generator implementation

I would like to use "hilo" generator but there is no any complete example how to create "specific" table as NH documentation says, and which values pass to it.
The following code fragments taken from NH tutorial
public class Cat
{
private Int64 id;
private string name;
private char sex;
private float weight;
public Cat()
{}
public virtual Int64 Id
{
get { return id; }
set { id = value; }
}
....
}
Mapper
<hibernate-mapping ...>
<class name="Cat" table="Cat">
<id name="Id" >
<column name="CatId" sql-type="Int64" not-null="true"/>
<generator class="hilo"/>
</id>
<property name="Name">
<column name="Name" length="16" not-null="true" />
</property>
....
</class>
</hibernate-mapping>
DB table "Cat"
CatId bigint NOT NULL
Name varchar(16) NOT NULL
Sex char(1) NULL
Weight real NULL
doesn't create anything in the database by default.
Parameters in the "id" node
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
gives "Invalid object name 'hi_value'" error message, without them I'm getting "Invalid object name 'hibernate_unique_key'."
Cuid.Comb that is shown in their tutorial works good but gives 99.12% of fragmentation when I added in a loop 20K cat objects.
Can somebody point me to an example of "hilo" implementation or give a tip what I'm missing?
Thanks.
This solution solved my problem. It's fairly simple, don't know why on nhibernate site there is no tiny example like that.
You may be running into NH-2687.

Hibernate HQL Query : How to set a Collection as a named parameter of a Query with composite key?

Given the following HQL Query:
from Foo foo where foo.id in (:fooIds)
but here i have composite key in the Id ex we have two PK1 and pk2 as Id's.
How can we implement this query..
how can i pass both paramets in setparameters function of query
My question is similar this question
HBM file containing composite key is present below
<?xml version="1.0"?>
<composite-id>
<key-property name="foo1" column="FOO1" type="java.lang.String" length="36"/>
<key-property name="foo2" column="FOO2" type="java.lang.Short" />
</composite-id>
<property name="EffectiveDt" type="java.sql.Date" column="EFFECTIVE_DT" />
<property name="effectiveTypeCd" type="java.lang.String" column="CERT_EFF_TYPE_CD" />
<property name="statusCd" type="java.lang.String" column="CERT_STATUS_CD" />
</class>
Are you using a composite id? Do you have a separate class representing the composite-id or do you have 2 fields in Foo and you want to search using them in your query?
Posting you Foo class would help!
I'm not 100% sure you can use in in this case. One thing you can do is to build the query manually with something like
String hqlQuery = "from Foo foo where "
boolean first = true;
for( ID id : fooids ) {
if( first ) {
hqlQuery += "foo.id = ?";
first = false;
} else {
hqlQuery += " OR foo.id = ?";
}
}
Query q = em.createQuery(hqlQuery);
int position = 0;
for( ID id : fooids ) {
q.setParameter(position, id);
position++;
}
You might want to double check the code, as I'm writing it here, so there's a big chance there's a typo or two.