package org.easyframe.tutorial.lesson3; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; import jef.database.Condition; import jef.database.DbClient; import jef.database.DbClientBuilder; import jef.database.ORMConfig; import jef.database.meta.FBIField; import jef.database.query.JpqlExpression; import jef.database.query.QueryBuilder; import jef.database.query.SqlExpression; import jef.tools.DateUtils; import jef.tools.string.RandomData; import org.easyframe.tutorial.lesson2.entity.Student; import org.junit.Test; /** * 这个案例演示更多的单表查询Criteria的用法,请对照执行后控制台上的打印出的SQL语句来验证。 * * @author jiyi * */ public class Case1 extends org.junit.Assert { DbClient db; public Case1() throws SQLException { db = new DbClientBuilder().setEnhancePackages("org.easyframe.tutorial").build(); // 准备数据时关闭调试,减少控制台信息 ORMConfig.getInstance().setDebugMode(false); db.dropTable(Student.class); db.createTable(Student.class); prepareData(5); ORMConfig.getInstance().setDebugMode(true); } /** * 根据 "模板对象" 的属性进行查询 * @throws SQLException */ @Test public void testSelect_example() throws SQLException { Student st = new Student(); st.setGender("M"); st.setGrade("2"); List<Student> students = db.select(st); System.out.println("2年级的男生:" + students.size()); // 用改写成count语句的方式再查一遍,检查两遍是否相等。 assertEquals(db.count(st.getQuery()), students.size()); } /** * 根据主键查询 * @throws SQLException */ @Test public void testSelect_Id() throws SQLException { Student st = new Student(); st.setId(1); st.setGender("M"); List<Student> students = db.select(st); System.out.println("ID为1的学生:" + students.size()); // 用改写成count语句的方式再查一遍,检查两遍是否相等。 assertEquals(db.count(st.getQuery()), students.size()); } /** * 使用in 作为查询条件 * @throws SQLException */ @Test public void testSelect_In() throws SQLException { Student st = new Student(); st.getQuery().addCondition(QueryBuilder.in(Student.Field.id, new int[] { 1, 3, 5, 7, 9 }) // 查询学号为 // 1,3,5,7,9的学生 ); List<Student> students = db.select(st); System.out.println("学号为1、3、5、7、9的学生:" + students.size()); // 用改写成count语句的方式再查一遍,检查两遍是否相等。 assertEquals(db.count(st.getQuery()), students.size()); } /** * 使用 Between 条件。 * @throws SQLException */ @Test public void testSelect_Between() throws SQLException { Student st = new Student(); // 查询出生日期在,1999-1-1到 2003-12-31之间的学生。 st.getQuery().addCondition(QueryBuilder.between(Student.Field.dateOfBirth, DateUtils.getDate(1999, 1, 1), DateUtils.getDate(2003, 12, 31))); // gender='M'的(男生) st.getQuery().addCondition(Student.Field.gender, "M"); List<Student> students = db.select(st); System.out.println("出生日期在范围内的男生:" + students.size()); assertEquals(db.count(st.getQuery()), students.size()); } /** * 在查询中使用 or、not * @throws SQLException */ @Test public void testSelect_AndOrNot() throws SQLException { Student st = new Student(); //三个Like条件,或 Condition isLastNam_ZhaoQianSun =QueryBuilder.or( QueryBuilder.matchStart(Student.Field.name, "赵"), QueryBuilder.matchStart(Student.Field.name, "钱"), QueryBuilder.matchStart(Student.Field.name, "孙") ); //或条件前面加上 NOT。 Condition isNot_ZhaoQianSun = QueryBuilder.not(isLastNam_ZhaoQianSun); //最终条件: 不姓'赵钱孙' 的女生。 st.getQuery().addCondition(QueryBuilder.and( isNot_ZhaoQianSun, QueryBuilder.eq(Student.Field.gender, "F") ) ); List<Student> students=db.select(st); System.out.println("不姓'赵钱孙'三姓的女生:" + students.size()); assertEquals(db.count(st.getQuery()), students.size()); } /** * 在查询中使用数据库函数 * * 注意观察——concat、lower等在不支持这些函数的数据库上,也能被转化为本地语言,正常运行。 * @throws SQLException */ @Test public void testSelect_Function() throws SQLException { Student st = new Student(); st.getQuery().addCondition(new FBIField("concat(lower(gender) , grade)"),"f2"); List<Student> students=db.select(st); assertEquals(db.count(st.getQuery()), students.size()); } /** * 在查询中使用 数据库函数 作为表达式的条件。 * * 注意观察——upper、nvl等在不支持这些函数的数据库上,也能被转化为本地语言,正常运行。 * @throws SQLException */ @Test public void testSelect_JpqlExpression() throws SQLException { Student st = new Student(); { //案例一 st.getQuery().addCondition(Student.Field.gender, new JpqlExpression("upper(nvl('f','m'))")); List<Student> students=db.select(st); assertEquals(db.count(st.getQuery()), students.size()); } st.getQuery().clearQuery(); //清除上一个查询条件 { //案例二: 查出出生日期最晚的学生 st.getQuery().addCondition(Student.Field.dateOfBirth, new JpqlExpression("(select max(dateOfBirth) from student)").bind(st.getQuery())); List<Student> students=db.select(st); assertEquals(db.count(st.getQuery()), students.size()); } } /** * 更灵活的用法—— * 还可以直接把一个SQL语句作为查询条件中的表达式 * @throws SQLException */ @Test public void testSelect_SqlExpression() throws SQLException { Student st = new Student(); //案例: 查出出生日期最晚的学生 st.getQuery().addCondition(Student.Field.dateOfBirth, new SqlExpression("(select max(date_of_birth) from student)")); List<Student> students=db.select(st); assertEquals(db.count(st.getQuery()), students.size()); } /** * 更灵活的用法—— * 1 可以使用一个表达式直接作为整个查询条件本身。 * 2 支持JDBC函数。 * @throws SQLException */ @Test public void testSelect_SqlExpression2() throws SQLException { Student st = new Student(); st.getQuery().addCondition( new SqlExpression("{fn timestampdiff(SQL_TSI_DAY,date_of_birth,current_timestamp)} > 100") ); List<Student> students=db.select(st); assertEquals(db.count(st.getQuery()), students.size()); } /** * 上述对Query条件的操作,在Update语句中同样适用。 * 同理,Delete语句也一样。 * @throws SQLException */ @Test public void testUpdate_SqlExpression() throws SQLException { Student st = new Student(); st.getQuery().addCondition(new FBIField("concat(lower(gender) , grade)"),"f2"); st.setGrade("6"); // update STUDENT set GRADE = '6' where lower(gender)||grade='f2' db.update(st); } 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("2"); data.add(st); } db.batchInsert(data); } }