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

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

内容简介:第一步,在实体中标记你的业务字段为@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!");
            }
        };
    }
}

点击标题见原文


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

查看所有标签

猜你喜欢:

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

The Starfish and the Spider

The Starfish and the Spider

Ori Brafman、Rod A. Beckstrom / Portfolio Hardcover / 2006-10-05 / USD 24.95

Understanding the amazing force that links some of today's most successful companies If you cut off a spider's leg, it's crippled; if you cut off its head, it dies. But if you cut off a st......一起来看看 《The Starfish and the Spider》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具