package org.easyframe.tutorial.lesson3;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import jef.database.Condition.Operator;
import jef.database.DbClient;
import jef.database.DbClientBuilder;
import jef.database.DbUtils;
import jef.database.Field;
import jef.database.ORMConfig;
import jef.database.query.Func;
import jef.database.query.JpqlExpression;
import jef.tools.string.RandomData;
import org.easyframe.tutorial.lesson2.entity.Student;
import org.easyframe.tutorial.lesson2.entity.UserBalance;
import org.junit.AfterClass;
import org.junit.Test;
public class CaseUpdate {
static DbClient db;
public CaseUpdate() throws SQLException {
db = new DbClientBuilder().setEnhancePackages("org.easyframe.tutorial").build();
// 准备数据时关闭调试,减少控制台信息
ORMConfig.getInstance().setDebugMode(false);
db.dropTable(Student.class, UserBalance.class);
db.createTable(Student.class, UserBalance.class);
prepareData(15);
ORMConfig.getInstance().setDebugMode(true);
}
@Test
public void testUpdate_Basic() throws SQLException {
{
// 查出一条对象,更新该条记录.
Student st = db.load(Student.class, 1);
st.setGender("M");
int updated = db.update(st);
// SQL: update STUDENT set GENDER = 'M' where ID=1
}
{
// 按主键随意更新一条记录
Student st = new Student();
st.setId(3);
st.setGrade("M");
int updated = db.update(st);
// SQL: update STUDENT set GRADE = 'M' where ID=3
System.out.println("更新" + updated + "条记录。");
}
{
// 按条件更新多条记录
Student st = new Student();
st.getQuery().addCondition(Student.Field.name, Operator.MATCH_ANY, "张");
st.setGender("M");
int updated = db.update(st);
// SQL: update STUDENT set GENDER = 'M' where NAME like '%张%' escape
// '/'
System.out.println("更新" + updated + "条记录。");
}
}
@Test
public void testUpdate_QueryAndUpdateMap() throws SQLException {
Student st = new Student();
st.setId(1);
st.setGender("M");
Map<Field, Object> updateMap = st.getUpdateValueMap();
System.out.println(updateMap);
updateMap.clear();
int updated = db.update(st); // no update here
}
@Test
public void testUpdate_concurrent_error() throws SQLException {
// 准备
UserBalance u = new UserBalance();
u.setAmout(100); // 一开始用户账上有100元钱
db.insert(u);
// 开始
UserBalance ub = db.load(UserBalance.class, 1);// 第一步,先查出用户账上有多少钱
// ... do some thing.
ub.setAmout(ub.getAmout() - 50);// 扣款50元
db.update(ub);// 将数值更新为扣款后的数值。
}
// 案例:乐观锁的update
@Test
public void testUpdate_Cas1() throws SQLException {
// 准备
UserBalance u = new UserBalance();
u.setAmout(100); // 一开始用户账上有100元钱
db.insert(u);
System.out.println(u.getId());
// 开始
int updated;
do {
UserBalance ub = db.load(UserBalance.class, 1);// 第一步,先查出用户账上有多少钱
ub.getQuery().addCondition(UserBalance.Field.id, ub.getId());
ub.getQuery().addCondition(UserBalance.Field.amout, ub.getAmout());
ub.setAmout(ub.getAmout() - 50);// 扣款50元
updated = db.update(ub);
} while (updated == 0);
}
// 案例:原子操作update
@Test
public void testUpdate_atom() throws SQLException {
UserBalance ub = new UserBalance();
ub.setId(1);
ub.prepareUpdate(UserBalance.Field.amout, new JpqlExpression("amout-50"));
int updated = db.update(ub);
}
// 案例:prepareUpdate的用法
@Test
public void testUpdate_MoreValues() throws SQLException {
UserBalance ub = new UserBalance();
ub.getQuery().setAllRecordsCondition();
// 将一个字段更新为另一个字段的值
ub.prepareUpdate(UserBalance.Field.todayAmount, UserBalance.Field.amout);
// 将updateTime更新为现在的值
ub.prepareUpdate(UserBalance.Field.updateTime, db.func(Func.now));
// 更新为另外两个字段相加
ub.prepareUpdate(UserBalance.Field.totalAmount, new JpqlExpression("todayAmount + amout"));
db.update(ub);
}
// 案例:更新值回写
@Test
public void testUpdate_Writeback() throws SQLException {
Student st = db.load(Student.class, 1);
st.prepareUpdate(Student.Field.id, 199);
int oldId = st.getId();
db.update(st);
System.out.println("Student的id从" + oldId + " 更新为" + st.getId());
}
// 案例:比较更新Map 3
@Test
public void testUpdate_Compare1() throws SQLException {
// 获得新的st对象
Student newSt = new Student();
newSt.setId(1);
newSt.setDateOfBirth(new Date());
newSt.setGender("M");
newSt.setName("王五");
// 从数据库中获得旧的st对象
Student oldSt = db.load(Student.class, 1);
// 把修改过的值记录到oldSt的updateValueMap中,相等的值不记入
DbUtils.compareToUpdateMap(newSt, oldSt);
// 如果需要记录字段修改记录,可以直接获取oldSt.getUpdateValueMap()来记录。
db.update(oldSt); // 只有数值不同的字段被更新。
}
@Test
public void testUpdate_fillValues() throws SQLException {
Student newSt = new Student();
newSt.stopUpdate();//不记录赋值操作
newSt.setId(1);
newSt.setDateOfBirth(new Date());
newSt.setGender("F");
newSt.setName("张三");
db.update(newSt);//由于未记录赋值变更,此处update操作无效。
DbUtils.fillUpdateMap(newSt);//将主键以外所有字段都记录为变更。
db.update(newSt);//update有效
}
private void prepareData(int num) throws SQLException {
List<Student> data = new ArrayList<Student>();
Date old = new Date(System.currentTimeMillis() - 864000000000L);
for (int i = 0; i < num; i++) {
// 用随机数生成一些学生信息
Student st = new Student();
st.setGender(i % 2 == 0 ? "M" : "F");
st.setName(RandomData.randomChineseName());
st.setDateOfBirth(RandomData.randomDate(old, new Date()));
st.setGrade(String.valueOf(RandomData.randomInteger(1, 6)));
data.add(st);
}
db.batchInsert(data);
}
@AfterClass
public static void close(){
db.close();
}
}