JPA实现领域驱动设计(DDD) 中值对象的持久化

什么是DDD值对象?

什么领域驱动设计(DDD) 值对象??

实现方式

利用JPA 中的@Embeddable@Embedded两个注解来实现值对象的持久化

单一值对象

单一对象可以利用嵌入的方式将值对象的属性映射到实体类,将值对象的属性 映射成表的字段 。

录入学生信息时,需要一个家庭住址的信息,则这个地址信息则可以设计成一个值对象AddressModel

import lombok.Data;

import javax.persistence.Embeddable;

/**
 * @author peter
 * date 2020/11/12 17:03
 */
@Data
@Embeddable
public class AddressModel {

    private String city;

    private String street;

    private Long lng;

    private Long lat;
}

学生Student

import lombok.Data;

import javax.persistence.*;

/**
 * @author peter
 * date 2020/11/12 17:08
 */
@Entity
@Data
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Embedded
    private AddressModel homeAddress;
	
	//省略其他信息....
}
在数据库中`student`表结构    

在这里插入图片描述

改变表中映射的字段的名称

利用@AttributeOverride注解来修改映射字段在数据库表的字段名称

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "city",column = @Column(name = "address_city")),
            @AttributeOverride(name = "street",column = @Column(name = "address_street")),
            @AttributeOverride(name = "lng",column = @Column(name = "address_lng")),
            @AttributeOverride(name = "lat",column = @Column(name = "address_lat")),
    })
    private AddressModel homeAddress;

根据值对象的单一属性查询或多属性的动态查询

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author peter
 * date 2020/11/12 17:11
 */
public interface StudentRepository extends JpaRepository<Student, Long>, JpaSpecificationExecutor<Student> {

    /**
     * 根据地址中的 city 来查询
     *
     * @param city
     * @return
     */
    List<Student> findByHomeAddress_City(String city);

    /**
     * 根据city、street 来动态查询
     * @param city
     * @param street
     * @return
     */
    default List<Student> query(String city, String street) {

        Specification<Student> specification = new Specification<Student>() {
            @Override
            public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();

                if (StringUtils.hasText(city)) {
                    predicates.add(cb.equal(root.get(Student_.HOME_ADDRESS).get("city"), city));
                }
                if (StringUtils.hasText(street)) {
                    predicates.add(cb.equal(root.get(Student_.HOME_ADDRESS).get("street"), street));
                }

                return cb.and(predicates.toArray(new Predicate[0]));
            }
        };
        return findAll(specification);
    }
}

多个值对象

利用 @ElementCollection 注解来实现持久化,在数据库会自动创建一个单独用于保存值对象数据的表,当实体类被删除时,自动删除对应的值对象的数据。

老师Teacher

import lombok.Data;

import javax.persistence.*;
import java.util.Set;

/**
 * @author peter
 * date 2020/11/12 18:15
 */
@Data
@Entity
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    @ElementCollection
    private Set<AddressModel> homeAddresses;

	//省略其他信息....
}

 数据库中值对象表结构

在这里插入图片描述

根据值对象的单一属性查询或多属性的动态查询

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author peter
 * date 2020/11/12 18:30
 */
public interface TeacherRepository extends JpaRepository<Teacher,Long>, JpaSpecificationExecutor<Teacher> {
    /**
     * 根据地址中的 city 来查询
     *
     * @param city
     * @return
     */
    List<Teacher> findByHomeAddresses_City(String city);

    /**
     * 根据city、street 来动态查询
     *
     * @param city
     * @param street
     * @return
     */
    default List<Teacher> query(String city, String street) {

        Specification<Teacher> specification = new Specification<Teacher>() {
            @Override
            public Predicate toPredicate(Root<Teacher> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();

                SetJoin<Teacher, AddressModel> addressModelSetJoin = root.joinSet(Teacher_.HOME_ADDRESSES);
                if (StringUtils.hasText(city)) {
                    predicates.add(cb.equal(addressModelSetJoin.get("city"), city));
                }
                if (StringUtils.hasText(street)) {
                    predicates.add(cb.equal(addressModelSetJoin.get("street"), street));
                }

                return cb.and(predicates.toArray(new Predicate[0]));
            }
        };
        return findAll(specification);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值