spring jpa json格式化 表名字段名变量名大小写 自定义查询排序问题

最近试用springboot jpa mysql和oracle 自定义查询排序功能,遇到很多问题

如何让表名、字段名、变量名能够一一映射,且方便自动化复用,且兼容主流数据库mysql、oracle,不用总是转换过来转换过去?
如何避免各种json和类的自动转换 和 各jpa框架的自动转换导致查询异常字段找不到问题?

  1. 表名,字段名,实体类字段名 大小写驼峰命名问题

sql查询数据,oracle中查询出来全是大写,所以决定把mysql设定为大小写敏感,把表名都定义全大写,下划线命名

修改/etc/my.cnf
lower_case_table_names = 0

每个字段都需要中文注释,所以把注释填写到表字段创建中,jpa自动生成表结构和注释,同时限制每个字段长度

@Column(name = “S_MTIME”, columnDefinition = "varchar(32) default ‘1970-01-01 00:00:00’ comment ‘修改时间’ ")
private String S_MTIME;

json格式化实体类,传递到前端使用,键名是方法名,而方法名要跟变量名和字段名关联起来且保持一致,json默认认为变量名为驼峰命名法,而与表字段名不一致

表字段 S_MTIME 变量名 sMtime 方法名 getSMtime 前端键 sMtime

所以采用命名规则为全大写下划线

表字段 S_MTIME 变量名 S_MTIME 方法名 getS_MTIME 前端键S_MTIME

为避免json自动转换驼峰命名问题 替换springboot默认的jackson

/**
* 替换jackson导致的序列化字段名大小写问题
* 1、直接配置系统环境变量,新建,变量名:TypeUtils.compatibleWithFieldName,变量值:true
* 2、“tEST” TypeUtils.compatibleWithJavaBean = true;
* 3、“t_EST” TypeUtils.compatibleWithFieldName = true;
* 4、在实体类中使用@JSONField(name = “name”),注意此注解是使用在get方法上,不是在声明属性的地方,务必注意。
* @return
*/
TypeUtils.compatibleWithJavaBean = true;
TypeUtils.compatibleWithFieldName = true;

为避免方法名和变量名的转换不一致,不使用注解生成get set,采用手动生成

最终jpa实体类如下:

/**
 * jpa实体类 学生
 */
@Entity
@Table(name = "W_STUDENT")
public class Student implements Cloneable,Serializable{

	@Id     //主键
//    @GeneratedValue(strategy = GenerationType.AUTO)     //自增
//    @GeneratedValue(generator = "system-uuid")
//    @GenericGenerator(name = "system-uuid", strategy = "uuid")
	@Column(name="ID", columnDefinition = "varchar(32) default '' comment '主键' ")
	private String ID;
	@Column(name = "S_MTIME", columnDefinition = "varchar(32) default '1970-01-01 00:00:00' comment '修改时间' ")
	private String S_MTIME;
	@Column(name = "S_ATIME", columnDefinition = "varchar(32) default '1970-01-01 00:00:00' comment '添加时间' ")
	private String S_ATIME;
	@Column(name = "S_FLAG", columnDefinition = "varchar(4) default '0' comment '1是0否' ")
	private String S_FLAG;
	@Column(name = "NAME", columnDefinition = "varchar(512) default 'name' comment '名字' ")    //255
	private String NAME;
	@Column(name = "SEX", columnDefinition = "varchar(4) default '0' comment '1男0女' ")
	private String SEX;
	@Column(name = "CLASS_CODE", columnDefinition = "varchar(32) default 'name' comment '班级' ")    //255
	private String CLASS_CODE;

	public Student(){

	}

	@Override
	public String toString() {
		return "Student{" +
				"ID='" + ID + '\'' +
				", S_MTIME='" + S_MTIME + '\'' +
				", S_ATIME='" + S_ATIME + '\'' +
				", S_FLAG='" + S_FLAG + '\'' +
				", NAME='" + NAME + '\'' +
				", SEX='" + SEX + '\'' +
				", CLASS_CODE='" + CLASS_CODE + '\'' +
				'}';
	}

	public String getID() {
		return ID;
	}

	public Student setID(String ID) {
		this.ID = ID;
		return this;
	}

	public String getS_MTIME() {
		return S_MTIME;
	}

	public Student setS_MTIME(String S_MTIME) {
		this.S_MTIME = S_MTIME;
		return this;
	}

	public String getS_ATIME() {
		return S_ATIME;
	}

	public Student setS_ATIME(String S_ATIME) {
		this.S_ATIME = S_ATIME;
		return this;
	}

	public String getS_FLAG() {
		return S_FLAG;
	}

	public Student setS_FLAG(String s_FLAG) {
		S_FLAG = s_FLAG;
		return this;
	}

	public String getNAME() {
		return NAME;
	}

	public Student setNAME(String NAME) {
		this.NAME = NAME;
		return this;
	}

	public String getSEX() {
		return SEX;
	}

	public Student setSEX(String SEX) {
		this.SEX = SEX;
		return this;
	}

	public String getCLASS_CODE() {
		return CLASS_CODE;
	}

	public Student setCLASS_CODE(String CLASS_CODE) {
		this.CLASS_CODE = CLASS_CODE;
		return this;
	}
}
  1. jpa查询排序字段转换找不到问题

继承相关类即可自动装配默认的一些查询工具


/**
 * sharding 分库 & 分表
 */
@Repository
public interface StudentRepository extends JpaRepository<Student, String>, JpaSpecificationExecutor {//实体类 主键类型 自定义查询
//    List<T> findAll();
//    List<T> findAll(Sort var1);
//    List<T> findAllById(Iterable<ID> var1);
//    <S extends T> List<S> saveAll(Iterable<S> var1);
//    void flush();
//    <S extends T> S saveAndFlush(S var1);
//    void deleteInBatch(Iterable<T> var1);
//    void deleteAllInBatch();
//    T getOne(ID var1);
//    <S extends T> List<S> findAll(Example<S> var1);
//    <S extends T> List<S> findAll(Example<S> var1, Sort var2);

    /**
     * JPQL查询 删除
     * @Cacheable 缓存方法操作
     */
    @Transactional
    @Modifying
    @Query("delete from Student t where t.ID in (?1) ")
    Integer selfDeleteAll(List<String> ids);


}

使用带下划线的字段来 自定义查询排序 会报错
No property S found for Student Did you mean ID ?

Pageable pageable =PageRequest.of(1, 5,  new Sort(Sort.Direction.DESC, "S_MTIME");
Page<Student> res = studentRepository.findAll(this.getSpecification(obj), pageable);

这个问题困扰很久,怎么都搜不到答案,直到后面终于决定跟踪一下源码
该方法构造排序sql
org.springframework.data.mapping.PropertyPath

 public static PropertyPath from(String source, TypeInformation<?> type) {
        Assert.hasText(source, "Source must not be null or empty!");
        Assert.notNull(type, "TypeInformation must not be null or empty!");
        return (PropertyPath)CACHE.computeIfAbsent(PropertyPath.Key.of(type, source), (it) -> {
            List<String> iteratorSource = new ArrayList();
            Matcher matcher = isQuoted(it.path) ? SPLITTER_FOR_QUOTED.matcher(it.path.replace("\\Q", "").replace("\\E", "")) : SPLITTER.matcher("_" + it.path);

            while(matcher.find()) {
                iteratorSource.add(matcher.group(1));
            }
            .......

其中这行尝试
** 正则操作 下划线作为了分隔符,导致带下划线的字段被拆分了多个字段**

Matcher matcher = isQuoted(it.path) ? SPLITTER_FOR_QUOTED.matcher(it.path.replace("\Q", “”).replace("\E", “”)) : SPLITTER.matcher("_" + it.path);

解决方案:

Pageable pageable =PageRequest.of(1, 5,  new Sort(Sort.Direction.DESC, "\\Q" + "S_MTIME" + "\\E");
Page<Student> res = studentRepository.findAll(this.getSpecification(obj), pageable);

???仅此还不够
可恶的jpa又仅仅不拆分 但却首字母给小写化了,结果使用了字段 s_MTIME
????

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值