如何在SpringBoot中使用Hibernate/JPA的@NaturalId?

栏目: Java · 发布时间: 5年前

内容简介:第一步,在实体中标记你的业务字段为@NaturalId:这里的code字段标记为@NaturalId,注意点:对于非可变id,将列标记为@NaturalId(mutable = false)和@Column(nullable = false, updatable = false, unique = true, ...)

第一步,在实体中标记你的业务字段为@NaturalId:

@Entity
public class Product implements Serializable {

    private static final long serialVersionUID = 1L;

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

    private String name;

    @NaturalId(mutable = false)
    @Column(nullable = false, updatable = false, unique = true, length = 50)
    private String code;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Product)) {
            return false;
        }
        Product naturalIdProduct = (Product) o;
        return Objects.equals(getCode(), naturalIdProduct.getCode());
        // including sku 
        // return Objects.equals(getCode(), naturalIdProduct.getCode())
            // && Objects.equals(getSku(), naturalIdProduct.getSku());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getCode());
        // including sku
        // return Objects.hash(getCode(), getSku());
    }

    @Override
    public String toString() {
        return "Product{" + "id=" + id + ", name=" + name + ", code=" + code + '}';
        // including sku
        // return "Product{" + "id=" + id + ", name=" + name + ", code=" + code + ", sku=" + sku + '}';
    }

这里的code字段标记为@NaturalId,注意点:

对于非可变id,将列标记为@NaturalId(mutable = false)和@Column(nullable = false, updatable = false, unique = true, ...)

对于可变id,将列标记为@NaturalId(mutable = true)和@Column(nullable = false, updatable = true, unique = true, ...)

使用NaturalId重写覆盖equals()并hashCode()方法

第二步,需要定义@NoRepositoryBean接口(NaturalRepository),在其中定义两个方法,命名findBySimpleNaturalId()和findByNaturalId()

@NoRepositoryBean
public interface NaturalRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {

    // use this method when your entity has a single field annotated with @NaturalId
    Optional<T> findBySimpleNaturalId(ID naturalId);
     
    // use this method when your entity has more than one field annotated with @NaturalId
    Optional<T> findByNaturalId(Map<String, Object> naturalIds);        
}

第三步, 实现此接口(NaturalRepositoryImpl),其中依赖使用Hibernate, Session, bySimpleNaturalId()和 byNaturalId() 方法。

@Transactional(readOnly = true)
public class NaturalRepositoryImpl<T, ID extends Serializable>
        extends SimpleJpaRepository<T, ID> implements NaturalRepository<T, ID> {

    private final EntityManager entityManager;

    public NaturalRepositoryImpl(JpaEntityInformation entityInformation,
            EntityManager entityManager) {
        super(entityInformation, entityManager);

        this.entityManager = entityManager;
    }

    @Override
    public Optional<T> findBySimpleNaturalId(ID naturalId) {

        Optional<T> entity = entityManager.unwrap(Session.class)
                .bySimpleNaturalId(this.getDomainClass())
                .loadOptional(naturalId);

        return entity;
    }

    @Override
    public Optional<T> findByNaturalId(Map<String, Object> naturalIds) {

        NaturalIdLoadAccess<T> loadAccess
                = entityManager.unwrap(Session.class).byNaturalId(this.getDomainClass());
        naturalIds.forEach(loadAccess::using);

        return loadAccess.loadOptional();
    }

}

第四步:在SpringBoot入口类中使用@EnableJpaRepositories(repositoryBaseClass = NaturalRepositoryImpl.class)注册此实施为基类

@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = NaturalRepositoryImpl.class)
public class NaturalIdApplication {

第五步:对于实体​​,编写一个经典的存储库:

@Repository
public interface ProductRepository<T, ID> extends NaturalRepository<Product, Long>{    
}

第六步:在您的服务中注入此类并调用findBySimpleNaturalId()或findByNaturalId()

@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = NaturalRepositoryImpl.class)
public class NaturalIdApplication {

    private static final Logger logger = Logger.getLogger(NaturalIdApplication.class.getName());

    private final ProductRepository productRepository;

    public NaturalIdApplication(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    public static void main(String[] args) {
        SpringApplication.run(NaturalIdApplication.class, args);
    }

    @Bean
    public ApplicationRunner init() {
        return args -> {

            // persist two products
            Product tshirt = new Product();
            tshirt.setName("T-Shirt");
            tshirt.setCode("014-tshirt-2019");
            // tshirt.setSku(1L);

            Product socks = new Product();
            socks.setName("Socks");
            socks.setCode("012-socks-2018");
            // socks.setSku(2L);

            productRepository.save(tshirt);
            productRepository.save(socks);

            Optional<Product> p1 = productRepository.findById(tshirt.getId());                 // find by ID
            Optional<Product> p2 = productRepository.findBySimpleNaturalId(tshirt.getCode()); // find by natural ID

            if (p1.isPresent() && p2.isPresent()) {
                System.out.println("p1: " + p1.get());
                System.out.println("p2: " + p2.get());
            } else {
                System.out.println("Not found!");
            }
        };
    }
}

点击标题见原文


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网络空间导论

网络空间导论

李良荣、方师师 / 复旦大学出版社 / 2018-6-1 / 38

在互联网蓬勃发展的今天,新闻传播学科该往何处去?在长达半个多世纪的深入研究后,李良荣教授及其团队给出了答案:从“小新闻”走向“大传播”,并撰写了这本开创性的教材:《网络空间导论》。 在本书中,互联网被定义为“空间”——持续演进的数字化现实。为了深刻把握网络空间的内涵,本书提供了六个维度的观察:技术应用、组织架构、政治经济、媒介文化、网络素养、安全治理,并以大胆且富有建设性的观点重新定义了新闻......一起来看看 《网络空间导论》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具