• 学习Spring-Data-Jpa(五)---可嵌入对象和元素集合的使用


    1、场景一:地址信息(省、市、县、详细地址)在很多实体中都需要,比如说作者有地址,订单也有地址,但是他们的地址并不能独立与他们存在,所以地址不能映射为实体,
    那么我们就需要在作者实体和订单实体中都添加这些地址信息。这时如果我们想要在地址信息中添加一个邮编,就需要在每一个用到地址的实体中都添加邮编字段,很是繁
    琐。面向对象编程的做法是,我们将地址信息封装到一个对象中,然后需要地址信息的实体如引用这个对象。直接这样做的话,如果地址类不实现Serializable接口,启动
    报错,实现了后,会把地址对象映射为二进制的数据库tinyblob字段,这显然不是我们想要的,什么好办法进行处理呢?

    JPA为我们提供了一组注解,来解决这个问题,@Embeddable/@Embedded。
    @Embeddable:指定一个类,该类的实例存储为所属实体的固有部分并共享该实体的标识。嵌入对象的每个持久属性或字段都映射到实体的数据库表。
    @Embedded:指定其值为可嵌入类的实例的实体的持久字段或属性。可嵌入类必须被注释为可嵌入的。

    在被@Embeddable标记的可嵌入类中的字段,也可以使用JPA的注解来进行设置。
    可以通过 @AttributeOverrides和@AttributeOverride来修改@Embedded标记的嵌入对象字段在本实体表中的映射字段名称,修改后原有可嵌入对象中的字段设置失效。
    多重嵌套用"."进行连接。

    注意:被引用对象和引用对象具有相同的生命周期时,才考虑使用内嵌对象。

    可嵌入地址类:
    /**
     *  地址对象
     *
     * @author caofanqi
     */
    @Data
    @Builder
    @Embeddable
    @NoArgsConstructor
    @AllArgsConstructor
    public class Address {
    
        private String province;
    
        private String city;
    
        private String county;
    
        /**
         * 可嵌入对象中的字段也可以使用@Column进行修饰
         */
        @Column(nullable = false)
        private String detailedAddress;
    
        private String zipCode;
    
    }

    作者实体中:

    /**
     * 作者实体
     *
     * @author caofanqi
     */
    @Data
    @Entity
    @Builder
    @Table(name = "jpa_author")
    @NoArgsConstructor
    @AllArgsConstructor
    public class Author {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        private String authorName;
    
    
        @Embedded
        @AttributeOverrides({
                @AttributeOverride(name = "detailedAddress",column = @Column(name = "addr_detailed")),
                @AttributeOverride(name = "zipCode",column = @Column(name = "addr_zip"))
        })
        private Address address;
    
    }


    2、场景二:作者有多个昵称我们要怎么映射呢?
    JPA为我们提供了@ElementCollection,指定基本类型或可嵌入类的实例集合。如果要通过集合表映射集合,则必须指定。
    属性 targetClass:集合指定了泛型可选,否者必须指定。必须是基本类型或可嵌入类型。
    属性 fetch:数据抓取策略。默认延迟加载。
    会为我们创建一张中间表,默认命名主实体 + "_" + 集合属性名称,默认外键名称,主实体类名 + "_" + 主实体主键。

    如果我们想要进行修改设置,可以使用@CollectionTable注解进行设置。

    注意,一般我们会直接在主实体中使用一个字段进行存放,存取的时候自己做一下处理(比如说逗号隔开的字符串),这样就不用多产生一张表了。

    作者实体中:
    /**
     * 作者实体
     *
     * @author caofanqi
     */
    @Data
    @Entity
    @Builder
    @Table(name = "jpa_author")
    @NoArgsConstructor
    @AllArgsConstructor
    public class Author {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        private String authorName;
    
    
        /**
         *  @ElementCollection 映射基本类型和可嵌入类型集合,可以使用@CollectionTable 指定额外产生表的名称,外键名称等。
         */
        @ElementCollection
        @CollectionTable(name = "jpa_author_nick",joinColumns = {@JoinColumn(name = "a_id",referencedColumnName = "id")})
        private Set<String> nickName;
    
    }


    3、场景三:如果作者有多个地址呢,比如说家庭地址,工作地址等,我们应该怎么办呢?
    我们可以将上面两种场景结合起来使用,将可嵌入的地址对象放到一个Map<String,Address> 中,这样生成的集合表就会将
    主实体id和map的key作为集合表的联合主键。
    同样我们可以使用@CollectionTable对集合表进行设置,使用@AttributeOverrides和@AttributeOverride设置数据库字段名称,
    只不过要添加前缀value.。
    可以使用@MapKeyColumn指定map的key在集合表中的列名,和其他一些设置,同@Column。默认列名是属性字段 + "_key"。

    作者实体:
    /**
     * 作者实体
     *
     * @author caofanqi
     */
    @Data
    @Entity
    @Builder
    @Table(name = "jpa_author")
    @NoArgsConstructor
    @AllArgsConstructor
    public class Author {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        private String authorName;
    
        /**
         * 一个作者有多个地址
         */
        @ElementCollection
        @MapKeyColumn(name = "addr_key")
        @CollectionTable(name = "jpa_author_address")
        @AttributeOverrides({
                @AttributeOverride(name = "value.detailedAddress",column = @Column(name = "addr_detailed")),
                @AttributeOverride(name = "value.zipCode",column = @Column(name = "addr_zip"))
        })
    
        private Map<String,Address> addresses;
    
    }

      对应生成的表

        

        

    源码地址:https://github.com/caofanqi/study-spring-data-jpa


  • 相关阅读:
    CF91 B. Queue
    CF18 C. Stripe
    CF767 A. Snacktower
    CF349 B. Color the Fence
    CF519 B. A and B and Compilation Errors
    NLog Helpper日志帮助类配置和使用
    一步一步搭建 .net core 应用
    使用webform、websevice来进行ajax请求操作
    各种奇技淫巧-持续更新
    防止表单提交时刷新页面-阻止form表单的默认提交行为
  • 原文地址:https://www.cnblogs.com/caofanqi/p/11811859.html
Copyright © 2020-2023  润新知