资讯专栏INFORMATION COLUMN

hibernate多对多,单个修改很伤神

zzzmh / 2432人阅读

摘要:因为的没有依赖模块,因而,数据字典无法调用模块中的项目类,如图所示因而,如果我们采用这种方式创建多对多的关系,会破坏结构或者框架结构。如图所示项目和图片的关系,一个项目有很多张图片,但是一张图片也可以被多个项目使用。。。。。

导读

客户单击项目详细时,会跳转到项目详细页面。用户单击红框中的加号,页面弹出选择标签页面。用户单击待选标签中的标签,当前标签会被保存到数据库中。

当然,项目标签与项目之间是多对多的关系,也就是说,一个项目可以有多个标签,一个标签对应多个项目,总体来说,它们之间是多对多的关系。

多对多的关系

多也是相对的多,就像导读中的项目和项目标签一样。这是从宏观上来说的多对多,但从微观上来看,其内部还是一对多的关系。一个项目可以有多个项目标签,一个项目标签可以对应多个项目。既然对各自来说,都是一对多的关系,为什么不这样写呢:

// 项目表
@Entity
@Table(name = "zq_project")
public class Project extends BaseObj {
 /**
 * 項目标签
 */
    @ManyToOne
    @JoinColumn(name = "attach_id")
    private List tagss;
}

//项目标签表
@Entity
@Table(name = "core_data_dict", uniqueConstraints = {@UniqueConstraint(columnNames = {"tenant_id", "code"}, name = "uk_dd_tid_code")})
public class DataDict extends ToString{

  /**
   * 項目
  */
    @ManyToOne
    @JoinColumn(name = "attach_id")
    private List projectList;
    
}

而是这样书写方式呢?

 /**
     * 添加项目标签,如果是标签来源于数据字典,则可以直接读取数据字典
     */
    @ManyToMany(fetch = FetchType.EAGER)
    @Fetch(FetchMode.SELECT)
    @JoinTable(
            name = "zq_project_tags",
            joinColumns = {@JoinColumn(name = "project_id")},
            inverseJoinColumns = @JoinColumn(name = "tag_code")
    )
    @JSONField(serialize = false)
    private List tagList;

因为这样书写,hibernate会根据项目和数据字典(项目标签放在数据字典表中)生成一个中间表,如图所示:

为什么不采用第一种方式呢?
1、第一种方式扩展性不好,破坏框架结构,为什么这么说?

项目标签放置在数据字典中,换句话,数据字典所存储的数据集不会经常改变。就像我们的新华字典,不会时常做版本更新。因而,类似于项目标签,数值型的单位呀、系统标量等,这些数据都不会时常改变。

而且,现在的项目都采用maven构建,什么是maven项目呢?很多博客都有详细介绍,我只做简单地介绍。maven是项目对象模型(POM),举一个简单的例子,我们在不使用maven创建项目时,往往需要拷贝jar包到项目中。然而,我们使用maven创建项目时,就会创建一个pom文件。我们在pomp文件中做配置,如果需要新的jar包,我们直接使用...

  
    com.alibaba
    fastjson
    ${fastjson.version}
  

当然,引用jar包是一回事,还有模块化构建项目。我们经常分模块构建项目,比如信息发布一个模块,核心层一个模块,自定义业务层一个模块。各个模块之间就像是Java一样,具有继承和关联关系。子pom文件可以使用父pom的所有jar包。如图所示:

层级非常严格,即便在同一个项目不同的模块中,我们如果想要调用另外一个模块的类时,也需要用dependency来引用其模块。比如,我们想要在platform-custom层调用platform-core层的类,我们需要在platform-custom的pom文件中写入依赖:

  
    com.zfounder.platform
    platform-core
   

但是,项目表是自定义业务范畴的,是在platform-custom模块中的,而数据字典是属于platform-core模块的。因为platform-core的pom没有依赖platform-custom模块,因而,数据字典无法调用platform-custom模块中的项目类,如图所示:

因而,如果我们采用这种方式创建多对多的关系,会破坏maven结构或者框架结构。

2、对于数据库的维护性不好。
对于项目来说,相同项目标签的可能有数条项目的记录,但是,每个项目都是唯一的,一个项目应该有多个标签,但现在的问题是,同一个项目的编号不同了,因为不同的项目标签,这就破坏了数据库的唯一性。

针对以上两种情况,我们应该使用中间表,来创建多对多的关系。如图所示:

这样简洁明快,也便于日后的维护工作。

哪些是多对多的关系

1、用户和角色之间的关系,一个用户可以有多重角色,一个角色可以对应多个用户。
2、既然说到了角色,自然说到角色所能管理的权限,比如当用户登录,根据用户的角色,需要展示哪些页面,可以操作该页面的哪些按钮,等等。这些都放在资源表中。如图所示:


3、项目和图片的关系,一个项目有很多张图片,但是一张图片也可以被多个项目使用。
4、。。。。

中间表一般都涉及两个字段,字段分别引用两张表的主键。

多对多的实例,以选择项目标签为例

我们在点击保存项目标签时,心想我们点击一次,保存一次,而项目类中项目标签对象是一个集合对象,我们应该创建这个集合,然后拿到前端传

过来的项目标签的code值(数据字典对应的是code值),通过数据字典的事务方法获取这个数据字典对象,再判断该对象的父类是不是项目标签。因为数据字典存储很多类字典,比如项目标签字典、单位字典、系统变量字典等等。然后保存这个数据字典,但结果事与愿违,它会覆盖数据库中原来的数据,这是更新数据,而不是保存数据,如图所示:

为什么会这样,因为,其底层使用的是merge方法,如代码所示:

 /**
 * @see com.zfounder.platform.core.dao.GenericDao#save(T)
 */
@SuppressWarnings("unchecked")
@Override
public T save(T object) {
    Session session = getSession();
    return (T) session.merge(object);
}

merger如果发现数据库存在该编号的对象,则执行update操作;如果不存在,则执行insert操作。因而,中间表,即项目标签表,已经存在该项目编号的id,所以,执行更新操作。

我们换一种思路,首先看项目类的部分源码:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "zq_project")
public class Project extends BaseObj {

    /**
     * 项目名称
     */
    @Column(name = "name")
    private String name;
    
    /**
     * 录入日期
     */
    @Column(name = "sign_date")
    private Date signDate;

    /**
     * 备注
     */
    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "remark", columnDefinition = "mediumtext")
    private String remark;

    /**
     * 预算金额
     */
    @Column(name = "budgetary_amount", precision = 10, scale = 2)
    private BigDecimal budgetaryAmount;
 
    /**
     * 工程起始时间
     */
    @Column(name = "start_time")
    private Date startTime;

    /**
     * 工程结束时间
     */
    @Column(name = "end_time")
    private Date endTime;

    /**
     * 添加项目标签,如果是标签来源于数据字典,则可以直接读取数据字典
     */
    @ManyToMany(fetch = FetchType.EAGER)
    @Fetch(FetchMode.SELECT)
    @JoinTable(
            name = "zq_project_tags",
            joinColumns = {@JoinColumn(name = "project_id")},
            inverseJoinColumns = @JoinColumn(name = "tag_code")
    )
    @JSONField(serialize = false)
    private List tagList;
}

因为项目标签时多对多的关系,当我们接收到前端传过来的项目编号,并调用项目的事务的get方法,创建当前项目瞬时态的对象时。hibernate根据项目标签表中的code值,创建项目标签(数据字典)的集合对象,并填充到tagList的集合中。我们只要在对集合对象上,添加从前端传过的code值,并通过code值创建项目标签(数据字典)的对象即可。因而,代码改成下面的方式:

这样保存就没问题了。

结尾

如果我们掌握了最基本知识是,就可以很容易掌握其他语言了。加油,致自己。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73636.html

相关文章

  • 相对的一对多多对一,hibernate伤神

    摘要:一对多和多对一一和多的概念通过以上的分析,我们知道一对多和多对一的关系。一对多和多对一的理论示例所以,一和多之间,并非绝对的关系,只是相对来说。项目和项目阶段也是一对多和多对一的关系。评论表和用户文章也是一对多和多对一的关系。 导读 最近公司在做这样的一个业务,由我来设计数据库,其中有有一个需求,根据原型图设计数据库,这也是我第一次独立设计数据库,因涉及公司的机密,只能展示部分原型图:...

    tianlai 评论0 收藏0
  • 慕课网_《Hibernate初探之对多映射》学习总结

    时间:2017年07月11日星期二说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:应用场景 1-1 多对多的应用场景 案例分析:企业项目开发过程中 一个项目可由多个员工参与开发 一个员工可同时参与开发多个项目 示意图 showImg(https://segmentfau...

    caozhijian 评论0 收藏0
  • Hibernate映射关系

    摘要:前言首先声明,这是一篇转发博客,不属于原创。关系映射有下面几种类型一对一外键关联映射单向一对一外键关联,使用,并设置了级联操作。设置了外键的名称为数据库字段名,如果不设置,则默认为另一类的属性名,外键的值是唯一的。 前言 首先声明,这是一篇转发博客,不属于原创。但是感觉很有用,所以在本人的博客中记录下来。 Hibernate Annotation关系映射有下面几种类型: 一对一...

    gougoujiang 评论0 收藏0

发表评论

0条评论

zzzmh

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<