Map class field name to column name in myBatis for insert - mybatis

I am using myBatis and trying create a db entry for the class User.
How can i map the different field names to the column names?
Do i need to or should myBatis know of them?
My User class looks like this:
public class User {
private String username;
private String email;
...
and the column names are:
user_name
e_mail
The myBatis create method looks like this:
void createUser(User user)
... i've tried like this:
<insert id="createUser" parameterType="...User">
INSERT INTO users (user_name, e_mail) VALUE
(#{username},#{email})
</insert>
and this:
<insert id="createUser" parameterType="...User">
INSERT INTO users (user_name, e_mail) VALUE
(#{user.username},#{user.email})
</insert>
I keep getting:
Parameter 'username' not found. Available parameters are [1, 0, param1, param2]
respectively Parameter 'user'

Found the answer:
The code should look like this:
void createUser(#Param("user")User user)
<insert id="createUser" parameterType="...User">
INSERT INTO users (user_name, e_mail) VALUE
(#{user.username},#{user.email})
</insert>

You shouldn't have to specify the #param annotation if you have getters/setters for those private variables. You don't indicate in your code snippet that you do. MyBatis should be smart enough to call the getter on the variables assuming you have one. If you look at the docs here http://mybatis.github.com/mybatis-3/sqlmap-xml.html#Parameters they have an example just like what you're doing above (note your first insert mapping is the correct one).
<insert id="insertUser" parameterType="User" >
insert into users (id, username, password)
values (#{id}, #{username}, #{password})
</insert>

Related

How to get db column value from Mybatis for sharding?

I use Mybatis to access db, and some tables is sharding by id with hash algorithm.
I want to write a Mybatis intecepter to change table name automatic, it need to get the sharding column value.
Table Entity:
#Data
#TableName("m_user")
public class User {
#TableId(type = IdType.AUTO)
private Integer id;
private String name;
private Integer age;
}
UserMapper sql:
#Select("select * from m_user where id = #{id2} and name = #{name2};")
List<User> selectByIdAndName(Integer id2, String name2);
I use boundSql.getParameterObject() and boundSql.getParameterMappings() to check, but I can not make sure whether the sharding column id is in sql and then get the value of the sharding column.
ParameterMappings values and ParameterObject values are here:
parameter mapping:ParameterMapping{property='id2', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}
parameter mapping:ParameterMapping{property='name2', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}
params:{id2=1, param1=1, name2=name1, param2=name1}
The parameters are Mapper function parameters, but I need sharding column id and value, program can only get id2 or param1.
How to get the db column and value from Mybatis?

mybatis - Passing multiple parameters on #One annotation

I am trying to access a table in my Secondary DB whose name I am obtaining from my Primary DB. My difficulty is to pass the "DB-Name" as a parameter into my secondary query, (BTW I am using MyBatis annotation based Mappers).
This is my Mapper
#SelectProvider(type = DealerQueryBuilder.class, method = "retrieveDealerListQuery")
#Results({
#Result(property="dealerID", column="frm_dealer_master_id"),
#Result(property="dealerTypeID", column="frm_dealer_type_id", one=#One(select="retrieveDealerTypeDAO")),
#Result(property="dealerName", column="frm_dealer_name")
})
public List<Dealer> retrieveDealerListDAO(#Param("firmDBName") String firmDBName);
#Select("SELECT * from ${firmDBName}.frm_dealer_type where frm_dealer_type_id=#{frm_dealer_type_id}")
#Results({
#Result(property="dealerTypeID", column="frm_dealer_type_id"),
#Result(property="dealerType", column="frm_dealer_type")
})
public DealerType retrieveDealerTypeDAO(#Param("firmDBName") String firmDBName, #Param("frm_dealer_type_id") int frm_dealer_type_id);
The firmDBName I have is obtained from my "Primary DB".
If I omit ${firmDBName} in my second query, the query is trying to access my Primary Database and throws out table "PrimaryDB.frm_dealer_type" not found. So it is basically trying to search for a table named "frm_dealer_type" in my Primary DB.
If I try to re-write the #Result like
#Result(property="dealerTypeID", column="firmDBName=firmDBName, frm_dealer_type_id=frm_dealer_type_id", one=#One(select="retrieveDealerTypeDAO")),
It throws an error that Column"firmDBName" does not exist.
Changing ${firmDBName} to #{firmDBName} also did not help.
I did refer to this blog - here
I want a solution to pass my parameter firmDBName from my primary query into secondary query.
The limitation here is that your column must be returned by the first #SELECT.
If you look at the test case here you will see that parent_xxx values returned by the first Select.
Your DealerQueryBuilder must select firmDBName as a return value and your column must map the name of the return column to that.
Your column definition is always wrong, it should be:
{frm_dealer_type_id=frm_dealer_type_id,firmDBName=firmDBName} or whatever it was returned as from your first select.
Again you can refer to the test case I have above as well as the documentation here http://www.mybatis.org/mybatis-3/sqlmap-xml.html#Nested_Select_for_Association

how to parameterize tablename in mybatis

I want to parameterize table_name:t_user_address_book(uid/500000).
for example: when uid = 1000, table_name = t_user_address_book0;
when uid = 500001, table_name = t_user_address_book1;
How to write?
public interface UserAddressBookMapper {
#Insert("insert into t_user_address_book? values(...)")
int upsert(Long uid, UserAddressBookMsg userAddressBookMsg);
}
You can choose the table with Mybatis XML code:
<choose>
<when test="uid gt 1000000">
<bind name="tableName" value="t_user_address_book2" />
</when>
<when test="uid gt 500000">
<bind name="tableName" value="t_user_address_book1" />
</when>
<otherwise>
<bind name="tableName" value="t_user_address_book0" />
</otherwise>
</choose>
Or you can compute the table name in the java and pass it as parameter.
Whatever your choice, the table name parameter in the query must be referenced with the $ notation instead of # since the value must replace the place holder as is to be part of the query and not being interpreted/bound/escaped as parameters are:
INSERT INTO ${tableName} ...
Despite use of XML, you can stick with annotations surrounding the query with <script> tags:
#Insert({"<script>",
"<choose> ...",
"INSERT ..."
"</script>"
})
Also when using Mapper interface with annotations, you need to name the parameters with there are more than 1:
#Insert("INSERT INTO table VALUES(#{uid}, #{userAddressBookMsg.propertyName1})")
int upsert(upsert(#Param("uid")Long uid, #Param("userAddressBookMsg") UserAddressBookMsg userAddressBookMsg);
However, it seems you want to split into multiple tables for volume issues, this is much complexity to handle while it would better be to keep a single table and look around on DB side about indexing and partitioning.
Quick response will be "no". It is not possible to give table name as parameter, because mybatis uses prepared statements.
I would suggest using table name as variable, and giving it to the statement string.
For example:
public interface UserAddressBookMapper {
static String tableName;
static void setTableName(String name) {
tableName = name;
}
#Insert({"insert into", tableName, "values(...)"})
int upsert(UserAddressBookMsg userAddressBookMsg);
You will have to set tableName before calling the method.

Select Map<Integer, Integer> using mybatis

I want to select Map for each record. Result class looks like
public class Mapping {
private String name;
private Map<Integer, Integer>;
}
SQL table has only three columns namely name, id, partner_id.
How can I create Map of Id to Partner Id for each name using mybatis?
you can use sqlSession.selectForMap, and give mybatis the column which will be processed as the key of map , such as name. then it will return
Map<String,Map<String,Object>>
as a result, but the value is Map, key is the column name, you need to transform it .

jpa select string found in where in caluse

I have a list of strings and i need to search them in my table then construct new class contain key as on of my search strings and value as my pojo if exist or null if not exist.
something like that :
Class MyMapper {
private String identificationKey;
private User user;
// Getter and Setter
}
My Expected Query:
SELECT NEW MyMapper(identificationKey, u) From User u where u.identification IN :identificationKeys
i need to select every identificationKey in identificationKeys even not exist