package org.easyframe.tutorial.lesson2; import java.sql.SQLException; import java.util.List; import jef.codegen.EntityEnhancer; import jef.database.Condition.Operator; import jef.database.DbClient; import jef.database.DbClientBuilder; import jef.database.query.Query; import jef.database.query.QueryBuilder; import org.easyframe.tutorial.lesson2.entity.Student; import org.easyframe.tutorial.lesson2.entity.StudentToLesson; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; public class Case1 { private static DbClient db; /** * 环境准备 */ @BeforeClass public static void setup() throws SQLException { db=new DbClientBuilder().build(); db.dropTable(Student.class,StudentToLesson.class); db.createTable(Student.class,StudentToLesson.class); } @AfterClass public static void close() { if (db != null) db.close(); } /** * 删表与建表 * @throws SQLException */ @Test public void testCreateTable() throws SQLException { db.dropTable(StudentToLesson.class); db.createTable(StudentToLesson.class); } /** * 自增主键的返回 * * 插入时,字段可以是自增的,操作完成后,自增值将会赋值到对象中。 * @throws SQLException */ @Test public void studentAutoIncreament() throws SQLException { Student s = new Student(); s.setName("Jhon Smith"); s.setGender("M"); s.setGrade("2"); db.insert(s); Assert.assertTrue(s.getId() > 0); System.out.println("自增键值为:" + s.getId()); } /** * 各种简单条件的单表查询 * * @throws SQLException */ @Test public void testLoadAndSelect() throws SQLException { // 创建一个模板对象,当模板对象主键有值时,按模板对象的主键查询。 { Student query = new Student(); query.setId(3); Student st = db.load(query); } // 直接按主键查询,当对象为复合主键时,可传入多个键值。 // 键值数量必须和复合主键的数量一致,顺序按field在emun Field中的出现顺序。 { Student st = db.load(Student.class, 3); StudentToLesson stl = db.load(StudentToLesson.class, 3, 1); } // load方法都是查询单值的,select方法可以查询多值 // 创建一个模板对象,当模板对象的字段有值时,按这些字段查询 // 类似于某H框架的 findByExample()。 { Student query = new Student(); query.setGender("F"); query.setGrade("2"); // 查出所有Gender='F' and grade='2'的记录。 List<Student> sts = db.select(query); } // 如果一个对象的复合主键没有全部赋值的情况,那么也当做普通字段对待 // 最终效果和findByExample()一样。 { StudentToLesson query = new StudentToLesson(); query.setLessionId(1); // 查出所有lessionId='1'的记录。 List<StudentToLesson> sts = db.select(query); } // 如果一个对象的主键都赋了值,非主键字段也赋值。那么非主键字段不会作为查询条件 // 因为框架认为主键字段足够定位记录,所以非主键不用作查询条件。 { Student query = new Student(); query.setGrade("1"); query.setId(12); // 查询条件为 id=12。grade = 12不用作查询条件 List<Student> sts = db.select(query); } } /** * 带有Like运算符的条件 * * @throws SQLException */ @Test public void testSelect_Like() throws SQLException { Student s = new Student(); // 在Student对象中添加Like条件 s.getQuery().addCondition(Student.Field.name, Operator.MATCH_ANY, "Jhon"); List<Student> sts = db.select(s); Assert.assertEquals(sts.size(), db.count(s.getQuery())); } /** * 带有大于、小于、Like等各种复杂的复合条件查询 * * 注意:由于有了enum类型的字段枚举,您将不会有机会拼写错误的字段名。 * 而且一旦字段发生变更,编译器也能帮您判断出问题的所在。 * * @throws SQLException */ @Test public void testSelect_LikeAndEtc() throws SQLException { Student s = new Student(); s.getQuery() .addCondition(Student.Field.name, Operator.MATCH_ANY, "Jhon") .addCondition(Student.Field.id, Operator.LESS, 100) .orderByDesc(Student.Field.grade); List<Student> sts = db.select(s); Assert.assertEquals(sts.size(), db.count(s.getQuery())); } /** * 更为复杂的查询 * 增加一个条件的正确写法。如果使用了Query对象,那么在Student中直接setXxx设值,不会用作查询条件。 * 因此,您必须用一致的写法来描述查询条件。 * * @throws SQLException */ @Test public void testSelect_LikeAndEtc2() throws SQLException { Student s = new Student(); // s.setGrade("3"); //在已经使用了Query对象中的情况下,此处设值不作为查询条件 s.getQuery().addCondition(Student.Field.grade, "3"); // 添加 grade='3'这个条件。 //当运算符为 = 时,可以省略不写。 s.getQuery().addCondition(Student.Field.name, Operator.MATCH_ANY, "Jhon"); s.getQuery().addCondition(Student.Field.id, Operator.LESS, 100); s.getQuery().orderByDesc(Student.Field.grade); List<Student> sts = db.select(s); Assert.assertEquals(sts.size(), db.count(s.getQuery())); } /** * 使用Like条件和in条件的更新和删除—— * 在学会使用Query对象来操作查询语句后,实现复杂条件下的update和delete也就是举一反三的事情了。 * * 看了这个例子后,我们会发现db.delete db.select db.update三个方法传入的实体对象,实际上是一个完整SQL语句的载体。 * 因此,这套API本质上不是为了实现单行记录的增删改查而设计的。这点和某H框架并不一样。 * * @throws SQLException */ @Test public void testUpdateAndDelete_WithLike() throws SQLException { Student s = new Student(); s.setGender("F"); s.getQuery().addCondition(Student.Field.name, Operator.MATCH_ANY, "Mary"); db.update(s); // 相当于执行 // update STUDENT set GENDER = 'F' where NAME like '%Mary%' s.getQuery().clearQuery();// 清除查询条件 s.getQuery().addCondition(Student.Field.id, Operator.IN, new int[] { 2, 3, 4 }); db.delete(s); // 相当于执行 // delete from STUDENT where ID in (2, 3, 4) } /** * 更新对象的主键列—— * 既然我们传入的实体是一个完整的SQL的载体,那么自然也可以做一些传统ORM很难实现的功能。 * 比如 —— 更新主键字段。 * */ @Test public void testUpdatePrimaryKey() throws SQLException { int id=insert(); Student q = new Student(); q.setId(id); q = db.load(q); q.getQuery().addCondition(Student.Field.id, q.getId()); q.setId(100); db.update(q); // 将id(主键)修改为100 // update STUDENT set ID = 100 where ID= 1 } /** * 另一种风格的条件书写。 * 为了满足不同偏好的小伙伴的要求,API支持好几种 条件的书写风格。这是使用QueryBuilder(QB)风格。 * * @throws SQLException */ @Test public void testSelect_LikeAndEtc3() throws SQLException { Query<Student> query = QueryBuilder.create(Student.class); query.addCondition(QueryBuilder.eq(Student.Field.grade, "3")); query.addCondition(QueryBuilder.matchAny(Student.Field.name, "Jhon")); query.addCondition(QueryBuilder.lt(Student.Field.id, 100)); query.orderByDesc(Student.Field.grade); List<Student> sts = db.select(query); Assert.assertEquals(sts.size(), db.count(query)); } /** * 另一种风格的条件书写。 * 为了满足不同偏好的小伙伴的要求,API支持好几种 条件的书写风格。这是使用Terms风格。 * * 和上例的效果是完全一样的 * @throws SQLException */ @Test public void testSelect_LikeAndEtc4() throws SQLException { Query<Student> query = QueryBuilder.create(Student.class); query.terms().eq(Student.Field.grade, "3") .and().matchAny(Student.Field.name, "Jhon") .and().lt(Student.Field.id, 100); query.orderByDesc(Student.Field.grade); List<Student> sts = db.select(query); Assert.assertEquals(sts.size(), db.count(query)); } private int insert() throws SQLException { Student s = new Student(); s.setName("Jhon Smith"); s.setGender("M"); s.setGrade("2"); db.insert(s); return s.getId(); } }