背景
项目有些数据使用mongodb 存储的,Spring data mongo给我们封装了许多通用的增删查改功能,我们继承MongoRepository 就自动包含了常见的增删查改。更神奇的是它可以根据方法名,自动转换为查询条件,比如根据名称查询,我们只需要定义一个方法(如下面实例代码),然后就能直接使用了,第一次接触时,简直惊为天人,这太好用了,MyBatis 还要写SQL。这个真正的见名知义。
public interface UserRepository extends MongoRepository<User,String> {
List<User> findByName(String name);
}
如果多个条件 直接And 连起来, 还支持Like , GreaterThan , LessThan ,Order By ,Top 等关键字,简直不要太方便。
使用泛滥
对于简单的查询,确实很好用,但是有些复杂的查询,举个例子,用户信息User 类,比如某家餐厅现在有活动给年满18,张姓客户,会员积分前5 的可以打5折,为了实现这个需求,“我”写了个查询方法如下,写出来发现方法名称很长,可能我屏幕小,一个方法调用就出现滚动条了
@Data
public class User {
@Id
private String id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private int age;
/**
* 性别
*/
private String gender;
/**
* 积分
*/
private int memberPoint;
/**
* 城市
*/
private String city;
}
public interface UserRepository extends MongoRepository<User,String> {
List<User> findByName(String name);
List<User> findTop5ByNameLikeAndCityAndAgeGreaterThanOrderByMemberPoint(String name,String city,int age);
}
List<User> selectUsers = userRepository.findTop5ByNameLikeAndCityAndAgeGreaterThanOrderByMemberPoint("张","杭州",18);
继续迭代
接着老板给我说,这个姓氏来我们店比较少,有几个来过一次,积分很少就享受这个优惠,不合理,要我加上会员积分大于100的条件。为了不影响原来的方法我新写了一个方法,当然是在原来基础上改的。于是这个类又多了个方法
public interface UserRepository extends MongoRepository<User,String> {
List<User> findByName(String name);
List<User> findTop5ByNameLikeAndCityAndAgeGreaterThanOrderByMemberPoint(String name,String city,int age);
List<User> findTop5ByNameLikeAndCityAndAgeGreaterThanOrderAndMemberPointGreaterThanByMemberPoint(String name,String city,int age,int memberPoint);
}
需求再次变更
老板说Top 5有点亏, 改成Top 3 。同样之前的方法可能由于被调用了,所以又新写了一个,于是类变成这样。
public interface UserRepository extends MongoRepository<User,String> {
List<User> findByName(String name);
List<User> findTop5ByNameLikeAndCityAndAgeGreaterThanOrderByMemberPoint(String name,String city,int age);
List<User> findTop5ByNameLikeAndCityAndAgeGreaterThanOrderAndMemberPointGreaterThanByMemberPoint(String name,String city,int age,int memberPoint);
List<User> findTop3ByNameLikeAndCityAndAgeGreaterThanOrderAndMemberPointGreaterThanByMemberPoint(String name,String city,int age,int memberPoint);
}
后来为了吸引用户老板又改成Top 10 ,还加了一些条件,然后我的查询方法又更加长了,看起来都差不多,就这样反反复复多次,我终于受不了, 虽然我们都知道MongoTemplate 可以自己组装查询条件,但谁也不愿意做第一个改变的人,终于我受不了了, 实在受不了方法名太长了,不换行或者拖动滚动条,完全不知道在调用什么方法
于是使用MongoTemplate 组装查询,不过也不好,总感觉担心Criteria 中字段拼写错误,导致查询失败。
public List<User> queryByCondition(String name, List<String> citys, int age,int topN){
Query query = new Query(Criteria.
where("name").regex(name + ".*").and("city").in(citys).and("age").gt(age)).limit(topN).with(Sort.by("memberPoint"));
return mongoTemplate.find(query, User.class);
}
上面问题也可以在UserRepository 方法上使用Query 注解,这样方法名可以不按照拼接“属性条件” 格式,可以使用用户自定义的,不过@Query 写查询条件也比较恶心。
这时才十分想念Mybatis ,还是写Sql爽。
你们最长的方法名多长,有人写过80个字符的方法名吗?