如何在Spring Boot中使用Hibernate Natural ID


本文是使用@NaturalIdSpring Data样式的Hibernate NaturalID()的快速实用指南。主要是,我们要公开的休眠,bySimpleNaturalId()并byNaturalId()通过典型的Spring数据存储库的方法,并把它们准确地叫我们称之为众所周知,findAll(),findOne(),等等。

Implementation 首先,让我们专注于所需类的实现。完成所有这些操作后,我们将能够为具有自然ID的实体提供存储库。

编写具有自然ID的实体 让我们考虑以下具有自动生成的ID和自然ID(该code列)的实体。这只是通过@NaturalId以下方式使用一个自然ID的典型实体:

@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;

    // getters and setters

    @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());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getCode());
    }
​
    @Override
    public String toString() {
        return "Product{" + "id=" + id + ", name=" + name + ", code=" + code + '}';
    }
}

编写NaturalRepository合同 我们首先编写一个名为的接口NaturalRepository。基本上,当我们要微调存储库时,我们可以依靠 @NoRepositoryBean注释。在我们的例子中,我们希望有两个,以丰富的春节数据的方法武库, 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);        
}

编写NaturalRepository实现 此外,我们扩展SimpleJpaRepository 类并实现NaturalRepository。通过扩展,SimpleJpaRepository我们可以通过添加所需的方法来自定义基础存储库。主要是,我们扩展了特定于持久性技术的存储库基类,并将此扩展用作存储库代理的自定义基类:

@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();
    }
​
}

将NaturalRepositoryImpl设置为基类 接下来,我们必须指示Spring Data依赖于我们自定义的存储库基类。在Java配置中,您可以repositoryBaseClass通过@EnableJpaRepositories注释使用属性 :

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

让我们看看它是如何工作的 现在,让我们看看它是否按预期工作。首先,让我们定义ProductRepository:

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

One Natural ID 此外,让我们保存两个具有唯一代码(自然ID)的产品:

Product tshirt = new Product();
tshirt.setName("T-Shirt");
tshirt.setCode("014-tshirt-2019");

Product socks = new Product();
socks.setName("Socks");
socks.setCode("012-socks-2018");
​
productRepository.save(tshirt);
productRepository.save(socks);

最后,让我们通过其自然ID查找T恤产品:

// this should return the t-shirt product wrapped in an Optional
Optional<Product> tshirt = productRepository.findBySimpleNaturalId("014-tshirt-2019");

注意:productRepository.findById(Object id)如果您要按自动生成的ID进行搜索,仍然可以使用 。

More Natural IDs 一个实体可以使用多个自然ID。例如,假设code 我们旁边也有 sku自然ID:

@NaturalId(mutable = false)
@Column(nullable = false, updatable = false, unique = true)
private Long sku;

现在,当我们坚持使用我们的产品时,它们将如下所示:

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);

查找T恤产品可以这样完成:

Map<String, Object> ids = new HashMap<>();
ids.put("code", "014-tshirt-2019");
ids.put("sku", 1L);
​

Optional<Product> tshirt = productRepository.findByNaturalId(ids);


原文链接:https://codingdict.com/