conditionally execute <selectKey> in MyBatis - mybatis

I have this problem. I need to execute selectKey to provide me with an id only when the supplied bookTypeId is null. Can it be done?
This is the insert function mapping:
<insert id="insert" parameterType="BookType">
<selectKey resultType="Integer" keyProperty="bookTypeId" order="BEFORE">
SELECT nextval('seq_book_type')
</selectKey>
INSERT INTO book_type(
book_type_id,
book_type_desc
)
VALUES(
#{bookTypeId},
#{bookTypeDesc}
)
</insert>

This is what I did after all:
<insert id="insert" parameterType="BookType">
<selectKey resultType="Integer" keyProperty="bookTypeId" order="BEFORE">
<if test="bookTypeId == null">SELECT nextval('seq_book_type')</if>
<if test="bookTypeId != null">SELECT #{bookTypeId}</if>
</selectKey>
INSERT INTO book_type(
book_type_id,
book_type_desc
)
VALUES(
#{bookTypeId},
#{bookTypeDesc}
)
</insert>
It works like a charm. Please anyone with myBatis experience, let me know if there is a better way than this.

Related

Criteria MongoTemplate achieve the query with not none conditions

I am a beginner in Spring MongoDB Criteria.
Once my database was mysql,if the variable is not none,I can do not none query like this:
<?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="org.mytest.modules.system.mapper.SysUserMapper">
<select id="getSysUser" resultType="org.mytest.modules.system.entity.SysUser">
select * from sys_user where del_flag = 0
<if test="username!=null and username!=''">
and username = #{username}
</if>
<if test="age!=null and age!=''">
and age = #{age}
</if>
<if test="profession!=null and profession!=''">
and profession = #{profession}
</if>
<if test="education!=null and education!=''">
and education = #{education}
</if>
<if test="dateStart!=null">
<![CDATA[ and DATE_FORMAT(time, '%Y-%m-%d %H:%T:%s') >=
DATE_FORMAT(#{dateStart} , '%Y-%m-%d %H:%T:%s') ]]>
</if>
<if test="dateEnd!=null">
<![CDATA[ and DATE_FORMAT(time, '%Y-%m-%d %H:%T:%s') <=
DATE_FORMAT(#{dateEnd} , '%Y-%m-%d %H:%T:%s') ]]>
</if>
</select>
</mapper>
Now my database change to mongoDB.How to do it with Criteria MongoTemplate with Criteria().andOperator?
SysUser sysUser = new SysUser();
// Create criteria object
Criteria criteria = Criteria.where("del_flag").is(0);
// Judge one by one
if (StringUtils.hasLength(sysUser.getUsername())) {
criteria = criteria.and("username").is(sysUser.getUsername());
}
if (Objects.nonNull(sysUser.getAge())) {
criteria = criteria.and("age").is(sysUser.getAge());
}
if (StringUtils.hasLength(sysUser.getProfession())) {
criteria = criteria.and("profession").is(sysUser.getProfession());
}
if (StringUtils.hasLength(sysUser.getEducation())) {
criteria = criteria.and("education").is(sysUser.getEducation());
}
if (Objects.nonNull(sysUser.getDateStart())) {
criteria = criteria.and("dateStart").gte(sysUser.getDateStart());
}
if (Objects.nonNull(sysUser.getDateEnd())) {
criteria = criteria.and("dateEnd").lte(sysUser.getDateEnd());
}
Query query = new Query(criteria);
List<SysUser> sysUserList = mongoTemplate.find(query, SysUser.class, "sys_user");

copy rows with myBatis

I'm trying to copy rows with Oracle and myBatis with this statement:
<?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
...
<insert id="copy" >
INSERT INTO ${table}
<foreach item="key" collection="keys" index="index" open="(" separator="," close=")">
${key}
</foreach>
VALUES
<foreach item="key" collection="map" index="index" open="(" separator="," close=")">
${key}
</foreach>
</insert>
</mapper>
--
for ( Map.Entry<Object, Object> entry2 : map.entrySet()) {
String key2 = (String) entry2.getKey();
Object value = null;
if (entry2.getValue() == null)
value = "NULL";
else if (entry2.getValue() instanceof java.sql.Timestamp)
{
//...
}
else if (entry2.getValue() instanceof Integer || entry2.getValue() instanceof Long ||
entry2.getValue() instanceof Short || entry2.getValue() instanceof java.math.BigDecimal
){
value = entry2.getValue();
}
else if (entry2.getValue().getClass().getName().equals("oracle.sql.CLOB"))
{
Clob clob=(Clob)entry2.getValue();
value= (String)clob.getSubString((long)1, (int)clob.length());
}
else{
value = "'" + entry2.getValue() + "'";
}
map.put(key2, value);
columans_valores.add("'" + key2 + "'");
}
copyService(map, map.keySet(), "table");
--
It works with most types, but CLOB and BLOB get their address copied instead or gets shrunk to 4000 bytes depending on the code i use to copy them, how do i deal with them?
Finally got it working with some tweaks:
To inform myBatis about the type used, switch $ for #
Avoid quotes
To prevent Oracle errors when inserting nulls, remove them from the map instead of
trying to insert null values

pg8000.core.ProgrammingError: 'could not determine data type of parameter $2'

I'm using pg.8000 (Postgres) and trying to run the following SELECT query
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
member_username
)
Where member.username is a String.
But I am getting the following error.
pg8000.core.ProgrammingError: ('ERROR', 'ERROR', '42P18', 'could not determine data type of parameter $2', 'postgres.c', '1350', 'exec_parse_message', '', '')
However, when I run same query using GUI tool, everything runs fine and I get the results. What is the problem?
You passed the parameter wrong, you should give a tuple, a list or a dictionary
Example with a tuple:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
(member_username,)
)
Example with a list:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
[member_username]
)
Example with a dictionary:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %(mname)s
""",
{'mname' : member_username}
)
http://initd.org/psycopg/docs/usage.html#query-parameters

JPA optimistic lock can't get the latest version

I am using the JPA's optimistic lock with spring data jpa and using spring retry for ConcurrencyFailureException, but something occurs that i can't understand.
my test code just like below:
#Repository
public interface AccountRepo extends JpaRepository<Account, String>, JpaSpecificationExecutor<Account> {
#Lock(LockModeType.OPTIMISTIC)
#Query(value = "select a from Account a where a.id = :id")
Account findOne(#Param("id") String id);
}
--------------------------------------------------------------------
#Service
public class AccountService {
#Qualifier("accountRepo")
#Autowired
private AccountRepo accountRepo;
#Transactional(value = "transactionManager", isolation = Isolation.READ_COMMITTED)
public Account saveOne(Account account){
return accountRepo.save(account);
}
public Account findOne(String id){
return accountRepo.findOne(id);
}
}
----------------------------------------------------------------------
#Transactional(value = "transactionManager", isolation = Isolation.READ_COMMITTED)
#Retryable(value = {ConcurrencyFailureException.class}, backoff = #Backoff(delay = 3000))
public void testOptimistic(){
Account account = accountService.findOne("abee19e08d3d4ee79d9f831c3ed78344");
account.setHistoryIncome(new BigDecimal("3300"));
account.setTodayTotalIncome(new BigDecimal("3300"));
account.setTodayOnlineIncome(new BigDecimal("3300"));
account.setAvaliableAmount(new BigDecimal("3300"));
accountService.saveOne(account);
AccountOperRecord accountOperRecord = new AccountOperRecord();
accountOperRecord.setId(BuildNoUtil.buildAccountOperRecordId());
accountOperRecord.setTrxType(TrxTypeEnum.EXPENSE.name());
accountOperRecord.setAvaliableAmount(account.getAvaliableAmount());
accountOperRecord.setOperAmount(new BigDecimal("100"));
accountOperRecord.setOrderId("4028b8815c813d64015c813e17f50000");
accountOperRecord.setOutTradeNo("2015061121001004400068549373");
accountOperRecord.setAccountId("abee19e08d3d4ee79d9f831c3ed78344");
accountOperRecordService.saveOne(accountOperRecord);
}
----------------------------------------------------------------------
#Controller
public class TestController extends BaseController {
#RequestMapping(value = "testOptimistic")
#ResponseBody
public JSONObject testOptimisticLock(){
JSONObject result = new JSONObject();
conjunctionService.testOptimistic();
result.put("code", "success");
return result;
}
}
i added a breakpoint at Account account = accountService.findOne("abee19e08d3d4ee79d9f831c3ed78344");, then i run a transaction in mysql to change the version of Account.
After that, the testOptimistic method throws the ConcurrencyFailureException and the method retried, in my opinion, it will success the next time but it failed again, finally it success at the third time, i just can not understand.
the logs of Hibernate SQL showed below
Hibernate: select account0_.id as id1_0_, account0_.create_time as create_t2_0_, account0_.creater as creater3_0_, account0_.edit_time as edit_tim4_0_, account0_.editor as editor5_0_, account0_.remark as remark6_0_, account0_.address as address7_0_, account0_.avaliable_amount as avaliabl8_0_, account0_.email as email9_0_, account0_.history_expense as history10_0_, account0_.history_income as history11_0_, account0_.merchant_name as merchan12_0_, account0_.name as name13_0_, account0_.phone as phone14_0_, account0_.settled_amount as settled15_0_, account0_.settling_amount as settlin16_0_, account0_.splited_amount as splited17_0_, account0_.today_offline_income as today_o18_0_, account0_.today_online_income as today_o19_0_, account0_.today_total_income as today_t20_0_, account0_.version as version21_0_ from account account0_ where account0_.id=?
Hibernate: select accountope0_.id as id1_1_0_, accountope0_.account_id as account_2_1_0_, accountope0_.avaliable_amount as avaliabl3_1_0_, accountope0_.oper_amount as oper_amo4_1_0_, accountope0_.order_id as order_id5_1_0_, accountope0_.out_trade_no as out_trad6_1_0_, accountope0_.remit_id as remit_id7_1_0_, accountope0_.settle_id as settle_i8_1_0_, accountope0_.split_batch_id as split_ba9_1_0_, accountope0_.trx_type as trx_typ10_1_0_ from account_oper_record accountope0_ where accountope0_.id=?
Hibernate: insert into account_oper_record (account_id, avaliable_amount, oper_amount, order_id, out_trade_no, remit_id, settle_id, split_batch_id, trx_type, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: update account set avaliable_amount=?, history_income=?, today_online_income=?, today_total_income=?, version=? where id=? and version=?
Hibernate: select account0_.id as id1_0_, account0_.create_time as create_t2_0_, account0_.creater as creater3_0_, account0_.edit_time as edit_tim4_0_, account0_.editor as editor5_0_, account0_.remark as remark6_0_, account0_.address as address7_0_, account0_.avaliable_amount as avaliabl8_0_, account0_.email as email9_0_, account0_.history_expense as history10_0_, account0_.history_income as history11_0_, account0_.merchant_name as merchan12_0_, account0_.name as name13_0_, account0_.phone as phone14_0_, account0_.settled_amount as settled15_0_, account0_.settling_amount as settlin16_0_, account0_.splited_amount as splited17_0_, account0_.today_offline_income as today_o18_0_, account0_.today_online_income as today_o19_0_, account0_.today_total_income as today_t20_0_, account0_.version as version21_0_ from account account0_ where account0_.id=?
Hibernate: select accountope0_.id as id1_1_0_, accountope0_.account_id as account_2_1_0_, accountope0_.avaliable_amount as avaliabl3_1_0_, accountope0_.oper_amount as oper_amo4_1_0_, accountope0_.order_id as order_id5_1_0_, accountope0_.out_trade_no as out_trad6_1_0_, accountope0_.remit_id as remit_id7_1_0_, accountope0_.settle_id as settle_i8_1_0_, accountope0_.split_batch_id as split_ba9_1_0_, accountope0_.trx_type as trx_typ10_1_0_ from account_oper_record accountope0_ where accountope0_.id=?
Hibernate: insert into account_oper_record (account_id, avaliable_amount, oper_amount, order_id, out_trade_no, remit_id, settle_id, split_batch_id, trx_type, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: update account set avaliable_amount=?, history_income=?, today_online_income=?, today_total_income=?, version=? where id=? and version=?
Hibernate: select version from account where id =?
Hibernate: select account0_.id as id1_0_, account0_.create_time as create_t2_0_, account0_.creater as creater3_0_, account0_.edit_time as edit_tim4_0_, account0_.editor as editor5_0_, account0_.remark as remark6_0_, account0_.address as address7_0_, account0_.avaliable_amount as avaliabl8_0_, account0_.email as email9_0_, account0_.history_expense as history10_0_, account0_.history_income as history11_0_, account0_.merchant_name as merchan12_0_, account0_.name as name13_0_, account0_.phone as phone14_0_, account0_.settled_amount as settled15_0_, account0_.settling_amount as settlin16_0_, account0_.splited_amount as splited17_0_, account0_.today_offline_income as today_o18_0_, account0_.today_online_income as today_o19_0_, account0_.today_total_income as today_t20_0_, account0_.version as version21_0_ from account account0_ where account0_.id=?
Hibernate: select accountope0_.id as id1_1_0_, accountope0_.account_id as account_2_1_0_, accountope0_.avaliable_amount as avaliabl3_1_0_, accountope0_.oper_amount as oper_amo4_1_0_, accountope0_.order_id as order_id5_1_0_, accountope0_.out_trade_no as out_trad6_1_0_, accountope0_.remit_id as remit_id7_1_0_, accountope0_.settle_id as settle_i8_1_0_, accountope0_.split_batch_id as split_ba9_1_0_, accountope0_.trx_type as trx_typ10_1_0_ from account_oper_record accountope0_ where accountope0_.id=?
Hibernate: insert into account_oper_record (account_id, avaliable_amount, oper_amount, order_id, out_trade_no, remit_id, settle_id, split_batch_id, trx_type, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: update account set avaliable_amount=?, history_income=?, today_online_income=?, today_total_income=?, version=? where id=? and version=?
Hibernate: select version from account where id =?
Hibernate: select version from account where id =?
you can see that select version from account where id =? execute two times at the third time, anyone can explain this?!
Thank you very much!

optional include with entity framework

I'm working on a manager. Depending on the conditions some include must be enforced in order to get eager loading. But sometime I don't want all the data so the includes should not be applied.
This is what I've got so far.
//INFO : public partial class Entities : DbContext
var Database = new Entities();
var result = Database.Department;
if (includeHospitalEmployee) { result.Include(a => a.HospitalEmployee); }
if (includeQuickScans) { result.Include(a => a.QuickScan); }
return result;
This doesn't work. The includes aren't loaded, although the includebooleans are set to true. Query results in;
SELECT
[Extent1].[Code] AS [Code],
[Extent1].[Discipline] AS [Discipline],
[Extent1].[FinancialCode] AS [FinancialCode],
[Extent1].[Name] AS [Name],
[Extent1].[DepartmentManagerId] AS [DepartmentManagerId],
[Extent1].[Show] AS [Show],
[Extent1].[Id] AS [Id]
FROM [dbo].[Department] AS [Extent1]
But strange enough if i do this, all include are working
//INFO : public partial class Entities : DbContext
var Database = new Entities();
var result = this.businessManagersFactory.Database.Department.Include(a => a.QuickScan);;
if (includeHospitalEmployee) { result.Include(a => a.HospitalEmployee); }
if (includeQuickScans) { result.Include(a => a.QuickScan); }
return result;
see the query
SELECT
[Project1].[C1] AS [C1],
[Project1].[Code] AS [Code],
[Project1].[Discipline] AS [Discipline],
[Project1].[FinancialCode] AS [FinancialCode],
[Project1].[Name] AS [Name],
[Project1].[DepartmentManagerId] AS [DepartmentManagerId],
[Project1].[Show] AS [Show],
[Project1].[Id] AS [Id],
[Project1].[C2] AS [C2],
[Project1].[Id1] AS [Id1],
[Project1].[StartDateTime] AS [StartDateTime],
[Project1].[EndDateTime] AS [EndDateTime],
[Project1].[Shared] AS [Shared],
[Project1].[ScanStatus] AS [ScanStatus],
[Project1].[Title] AS [Title],
[Project1].[Count] AS [Count],
[Project1].[Comment] AS [Comment],
[Project1].[HospitalEmployeeId] AS [HospitalEmployeeId],
[Project1].[DepartmentId] AS [DepartmentId]
FROM ( SELECT
[Extent1].[Code] AS [Code],
[Extent1].[Discipline] AS [Discipline],
[Extent1].[FinancialCode] AS [FinancialCode],
[Extent1].[Name] AS [Name],
[Extent1].[DepartmentManagerId] AS [DepartmentManagerId],
[Extent1].[Show] AS [Show],
[Extent1].[Id] AS [Id],
1 AS [C1],
[Extent2].[Id] AS [Id1],
[Extent2].[StartDateTime] AS [StartDateTime],
[Extent2].[EndDateTime] AS [EndDateTime],
[Extent2].[Shared] AS [Shared],
[Extent2].[ScanStatus] AS [ScanStatus],
[Extent2].[Title] AS [Title],
[Extent2].[Count] AS [Count],
[Extent2].[Comment] AS [Comment],
[Extent2].[HospitalEmployeeId] AS [HospitalEmployeeId],
[Extent2].[DepartmentId] AS [DepartmentId],
CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
FROM [dbo].[Department] AS [Extent1]
LEFT OUTER JOIN [dbo].[QuickScan] AS [Extent2] ON [Extent1].[Code] = [Extent2].[DepartmentId]
) AS [Project1]
ORDER BY [Project1].[Code] ASC, [Project1].[C2] ASC
Why is this behaviour and how to get it working properly?
regards
I don't have access to Visual Studio to confirm but you will probably find that assigning the return from the call to Include will sort it - it will be something like a QueryObject that implements IQueryable
var Database = new Entities();
IQueryable<Department> result = Database.Departments;
if (includeHospitalEmployee) { result = result.Include(a => a.HospitalEmployee); }
if (includeQuickScans) { result = result.Include(a => a.QuickScan); }
return result;