一、问题背景描述
在应用开发过程中,我们需要将数据库中的数据要与Web浏览器进行‘交互’,这时就需要Java程序,就做了中间的适配器。

在这个过程中,每个数据的传输都是通过网络进行传输对象的。这时为了方便传输对象,我们需要进行序列化操作。这里我们主要讲主流的序列化方式:JSON序列化。
二、主流的开发模式
目前主流的开发模式是:数据库中的数据通过ORM映射转换成Java实体对象Entity(也可以用其他的表示,这里用Entity表示实体对象),再转换成DTO(传输对象),最后在通过http协议传输给Web浏览器。如下图所示:

上述的传输过程中,如果是简单的数据类型(如Integer、String等简单的数据类型),但遇到浮点整形类型数据(因为在计算过程中会出现异常)、枚举类型、时间类型等数据类型,这时就会出现不同程度的问题。而这个问题,又会影响到整个项目的健壮程度。
(浮点整形类型数据好处理,使用BigDecimal代替就好了)
如果该问题得不到统一的且合理的解决方案,这直接会影响整个项目的容错率。例如,不同的程序员有自己不同处理特殊类型数据时,会有自己的处理方式,导致整个项目对该类型数据的处理方式不一致,对后续的维护工作增加了难度。
三、数据库到Java程序之间的数据传输
这里数据库相关技术以JPA+Mysql为例。
1. 枚举类型
1.1 默认处理方式
Java程序对枚举类型的默认处理方式时:
- 数据库中默认的存储类型时
int类型, - 从
java程序保存近数据库中,是按枚举类型值的顺序(从0开始存储) - 从
数据库中读取到Java程序中,方式也是一样的。
实战案例:
枚举类型:
public enum StatusType {
DISABLE(0, "冻结", "freeze"),
ENABLE(1, "启用", "enable");
@EnumValue
private final Integer code;
private final String name;
private final String decs;
StatusType(Integer code, String name, String decs) {
this.code = code;
this.name = name;
this.decs = decs;
}
// 其他常见 api
}
@Entity
@Table(name = Role.TABLE)
@Data
public class Role extends BaseEntity {
public final static String TABLE = "role";
private static final long serialVersionUID = 6142819771142346343L;
/**
* 角色名
*/
@Column(name = "name", columnDefinition = "varchar(64) comment '角色名'")
private String name;
/**
* 角色状态
*/
@Column(name = "status", columnDefinition = "tinyint(1) comment '用户状态1、启用,0、停用'")
private StatusType status = StatusType.ENABLE;
}
repository类:
public interface RoleRepository extends JpaRepository<Role, Long>, JpaSpecificationExecutor<Role> {
}
注意:添加测试,在这就不测试了。结果就是,上述的说法。
1.2 缺点
上述缺点描述:
- 默认的处理方式,不具备可读性(尤其是在程序出现异常数据时。默认的赋值方式,给程序员错觉,很不好排查)。
- 自己设计的
code几乎无效,完全违背了设计的初衷。
1.3 自定义处理方式
查看该篇文章有详细解释(第五章):实战JPA,如何优雅解决实际开发问题?
1.4 优点
优点描述:
- 原先设计的
code用上了,并按照该值存进了数据库中。- 程序中的数据出现了
bug,增加了可读性,让程序员能更快定位错误。- 自定义
code值,更好扩展。比如将所有的枚举类型数据进行统一管理,增强了项目的扩展性。

本文探讨了Java开发中数据序列化遇到的问题,特别是处理枚举类型和时间类型时的难点及解决方案,强调了统一处理方式的重要性。
1169

被折叠的 条评论
为什么被折叠?



