一、问题背景描述
在应用开发过程中,我们需要将数据库
中的数据要与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 自定义处理方式
1.4 优点
优点描述:
- 原先设计的
code
用上了,并按照该值存进了数据库中。- 程序中的数据出现了
bug
,增加了可读性,让程序员能更快定位错误。- 自定义
code
值,更好扩展。比如将所有的枚举类型
数据进行统一管理,增强了项目的扩展性。
2. 时间类型
四、Java程序到Web浏览器之间的数据传输