首先,让我们关注所需类的实现。完成所有这些后,我们将能够为具有自然ID的实体提供存储库。
用自然ID编写实体
让我们考虑以下具有自动生成ID和自然ID(code列)的实体。这只是一个使用一个自然ID的典型实体@NaturalId:@实体
public class Product implements Serializable {private static final long serialVersionUID = 1L ;@ID@GeneratedValue(策略 = GenerationType。IDENTITY)私人 长 身份 ;私有 字符串 名称 ;@NaturalId(mutable = false)@Column(nullable = false,updatable = false,unique = true,length = 50)私有 字符串 代码 ;// getter和setter@覆盖public boolean equals(Object o){ if(this == o){ 返回 true ; } if(!(o instanceof Product)){ 返回 false ; } 产品 naturalIdProduct =(产品)o ; 返回 对象。等于(引用代码(),naturalIdProduct。引用代码());}@覆盖public int hashCode(){ 返回 对象。hash(getCode());}@覆盖public String toString(){ 返回 “Product {” + “id =” + id + “,name =” + name + “,code =” + code + '}' ;}
}
编写NaturalRepository合同我们首先编写一个名为的接口NaturalRepository。基本上,当我们想要微调存储库时,我们可以依赖 @NoRepositoryBean注释。在我们的例子中,我们想要用另外两个来丰富Spring Data方法库, findBySimpleNaturalId()并且findByNaturalId() :@NoRepositoryBean
public interface NaturalRepository < T,ID extends Serializable > extends JpaRepository < T,ID > {//当您的实体具有使用@NaturalId注释的单个字段时,请使用此方法可选< T > findBySimpleNaturalId(ID naturalId);//当您的实体具有多个使用@NaturalId注释的字段时,请使用此方法可选< T > findByNaturalId(Map < String,Object > naturalIds);
}
编写NaturalRepository实现此外,我们扩展了SimpleJpaRepository 类并实现了NaturalRepository。通过扩展,SimpleJpaRepository我们可以通过添加我们需要的方法来定制基本存储库。主要是,我们扩展了特定于持久性技术的存储库基类,并将此扩展用作存储库代理的自定义基类:@Transactional(readOnly = true)
public class NaturalRepositoryImpl < T,ID 扩展 Serializable >扩展 SimpleJpaRepository < T,ID > 实现 NaturalRepository < T,ID > {private final EntityManager entityManager ;公共 NaturalRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager){ super(entityInformation,entityManager); 这个。entityManager = entityManager ;}@覆盖public Optional < T > findBySimpleNaturalId(ID naturalId){ 可选< T > entity = entityManager。解包(会话。类) 。bySimpleNaturalId(此。getDomainClass()) 。loadOptional(naturalId); 回报 实体 ;}@覆盖public Optional < T > findByNaturalId(Map < String,Object > naturalIds){ NaturalIdLoadAccess < T > loadAccess = entityManager。解包(会话。类)。byNaturalId(此。getDomainClass()); naturalIds。forEach(loadAccess :: using); return loadAccess。loadOptional();}
}
将NaturalRepositoryImpl设置为基类接下来,我们必须指示Spring Data依赖于我们的自定义存储库基类。在Java配置中,您可以repositoryBaseClass通过@EnableJpaRepositories注释使用该属性来执行此操作 :@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = NaturalRepositoryImpl。类)公共 类 NaturalIdApplication {...
}
让我们看看它是如何工作的现在,让我们看看它是否按预期工作。首先,让我们定义ProductRepository:@Repository
public interface ProductRepository < T,ID > extends NaturalRepository < Product,Long > { }一个自然身份证此外,让我们保存两个具有唯一代码(自然ID)的产品:产品 tshirt = 新 产品();
T恤。setName(“T-Shirt”);T恤。setCode(“014-tshirt-2019”);产品 袜子 = 新 产品();袜子。setName(“袜子”);袜子。setCode(“012-socks-2018”);productRepository。保存(T 恤);productRepository。保存(袜子);最后,让我们通过它的自然ID 找到T-Shirt产品://这应该返回包装在Optional中的T恤产品
可选< Product > tshirt = productRepository。findBySimpleNaturalId(“014-tshirt-2019”);注意:productRepository.findById(Object id)如果要按自动生成的ID进行搜索,仍可以使用 。更多自然ID
实体可以使用多个自然ID。例如,让我们假设code 我们旁边还有 sku自然ID:@NaturalId(mutable = false)
@Column(nullable = false,updatable = false,unique = true)私人 龙 sku ;现在,当我们坚持我们的产品时,它们将如下所示:产品 tshirt = 新 产品();
T恤。setName(“T-Shirt”);T恤。setCode(“014-tshirt-2019”);T恤。setSku(1L);产品 袜子 = 新 产品();袜子。setName(“袜子”);袜子。setCode(“012-socks-2018”);袜子。setSku(2L);productRepository。保存(T 恤);productRepository。保存(袜子);找到T恤产品可以这样做:Map < String,Object > ids = new HashMap <>();
ids。put(“code”,“014-tshirt-2019”);ids。put(“sku”,1L);可选< Product > tshirt = productRepository。findByNaturalId(ids);