对 Entity 的初步构思

本文是《轻量级 Java Web 框架架构设计》的系列博文。

Hibernate 框架确实挺好,最早我们使用它的 ORM 配置文件,当时确实觉得有些累。于是后来就有了 Doclet 这样的技术,这样 ORM 配置文件就不用写了,但 Java Doc 却要写一大堆。直到最后,救星终于来了!它就是 JPA。随后, Hibernate 就成为 JPA 规范中的一个实现了,这表明了什么呢?注解才是去掉繁重的 XML 配置文件的真正解决之道(至少目前是这样,将来就不好说了)。我也深受了 JPA 的影响,想搞一个更加轻量级的 JPA,目的就是实用性强,此外还需要通过编码规范来确保每个程序员都能正确的完成自己的工作任务。

领域建模是 Hibernate 所推崇的开发方式,首先要根据业务需求确定 Domain,用 Hibernate 的话来讲就是 Entity(实体)。下面以 Product  Entity为例,描述一下我对 Entity 的构想:

@Table("product")
public class Product extends Entity {
    @Column("product_type_id")
    private long productTypeId;

    @Column("product_name")
    private String productName;

    @Column("product_code")
    private String productCode;

    @Column("price")
    private int price;

    @Column("description")
    private String description;

    public long getProductTypeId() {
        return productTypeId;
    }

    public void setProductTypeId(long productTypeId) {
        this.productTypeId = productTypeId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    ... 省略其他 getter/setter 方法
}

第1行:使用 @Table 注解来定义 Product 实体对应于 product 表,这注解与 JPA 的 @Entity + @Table 作用相同,可认为这里简化了配置。

第2行:该 Product Entity 继承于 Entity,这样做是为了在父类 Entity 中封装每个业务实体所共有的属性,例如:id,MySQL 建议我们每张表最好有一个 id 主键,我想还是它的道理的。

第3行:使用 @Column 注解标明 productName 属性与 product_name 列相对应。当然,这里是不是也要 JPA 那样,指定 Column 的数据类型以及长度与精度呢?我个人认为这是不必要的,因为在实际开发工作当中,一般是由架构师或者 DBA 来创建数据库表结构(即 Database Schema),我们拿到这份表结构文档之后,在此基础之上再编写相应的 Entity。所以,我们在编写这个 Entity 的时候,可以假设数据库已经存在了,而无需再像 Hibernate 那样根据 Entity 中的注解自动生成数据库的 DDL。这样自动化的生成,其实对项目的风险也挺大的。此外,这里推荐对每个属性都配置 @Column 注解,不管它们的拼写是否完全一致。当然不写 @Column 注解也是可以的,但是这个不妨作为编码规范,把 Code Review 的任务交给架构师去吧。

下面再来看看这个 Entity 类吧:

public abstract class Entity extends Bean {
    @Column("id")
    private long id;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }
}

它是一个抽象类。其实就包含一个 id 属性,当然可以从业务需求中可以尽可能的抽象出公共的属性,统一在这里定义。注意,该类又继承了一个 Bean 类,那么这个 Bean 类又是怎样的呢? 

最后再来看看这个 Bean 类吧:

public abstract class Bean implements Serializable {
    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }

    public String toJson() {
        return JSONUtil.toJSON(this);
    }

    public String toXML() {
        return XMLUtil.toXML(this);
    }
}
它也是一个抽象类。首先,它实现了 Serializable 接口,也就是可以序列化了,这样更有助于网络传输。为什么要将序列化接口实现在最基础的 Bean 类中呢?这样做是因为,继承该类的其他子类无需再次实现这个序列化接口了,配置也更加简单了。 其次,这里还定义了一些公共方法,Java 自带的 hashCode()、equals()、toString() 方法,这些方法均使用了 Apache Commons 的  lang 包来实现。  最后,还有两个非常实用的方法,toJSON() 与 toXML() 方法,其作用我想已经不言而喻了。


如果有了以上这样的继承体系,那么每个 Entity 是不是更加强大了呢?此外,Bean 类还可用于非 Entity 类上,这样它的功能又进一步得到了复用。

请大家对以上构思,提点建议或意见吧!


补充(2013-09-03)

根据大家提供的建议,我将 Entity 定义为以下结构:

public class Product extends BaseEntity {
    private long productTypeId;
    private String productName;
    private String productCode;
    private int price;
    private String description;

    public long getProductTypeId() {
        return productTypeId;
    }

    public void setProductTypeId(long productTypeId) {
        this.productTypeId = productTypeId;
    }

    ...
}

这里没有任何的注解,只是继承了 BaseEntity 这个类(也就是上文提到的 Entity 抽象类,为了便于理解,这里将其重命名为 BaseEntity)。Java 类中的 Field 会自动映射为数据库中的 Column,映射规则只是将“驼峰风格”的 Field 与“下划线”风格的 Column 进行映射,例如:productTypeId 对应于 product_type_id。这些映射规则完全由框架来实现,对程序员完全透明,程序员要做的事情就是 extends BaseEntity 了。 

是不是比 JPA 要简单呢?那么框架又是如何实现的呢?敬请期待...

转载于:https://my.oschina.net/huangyong/blog/158481

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值