编辑.虽然扩展基础存储库类并添加插入方法可以使更优雅的解决方案似乎在实体中实现Persistable.见可能的解决方案2

我正在使用springframework.data.jpa创建一个服务,使用Hibernate作为ORM,使用JpaTransactionManager.

我的实体存储库扩展了org.springframework.data.repository.CrudRepository

我正在使用遗留数据库,该数据库使用有意义的主键而不是自动生成的ID

这种情况不应该真的发生,但是由于测试中的错误我遇到了它.订单表具有OrderNumber(M000001等)的有意义的键.主键值在代码中生成,并在保存之前分配给对象.旧数据库不使用自动生成的ID密钥.

我有一个创建新订单的交易.由于存在错误,我的代码生成了一个已存在于数据库中的订单号(M000001)

执行repository.save会导致更新现有订单.我想要的是强制插入并由于重复的主键导致事务失败.

我可以在每个存储库中创建一个Insert方法,在执行保存之前执行查找,如果存在行则执行失败.某些实体具有带有OrderLinePK对象的复合主键,因此我无法使用基本弹簧FindOne(ID id)方法

在春季JPA中有这样一种干净的方法吗?

我之前使用spring / Hibernate和我自己的基础库创建了一个没有jpa存储库的测试服务.我实现了Insert方法和Save方法,如下所示.

这似乎工作正常.

使用getSession().saveOrUpdate的save方法给出了我现在正在经历的现有行更新.

使用getSession()的insert方法.使用重复的主键保存失败,如我所愿.

@Override

public Order save(Order bean) {

getSession().saveOrUpdate(bean);

return bean;

}

@Override

public Order insert(Order bean) {

getSession().save(bean);

return bean;

}

可能的解决方案1

可能不是最有效的,因为我们正在进行额外的检索以检查插入之前行的存在,但它是主键.

除了save之外,还扩展存储库以添加插入方法.这是第一次削减.

我必须将密钥传递给插入以及实体.我可以避免这个吗?

我实际上并不想要返回数据. entitymanager没有exists方法(确实存在只需要计数(*)来检查行的存在吗?)

import java.io.Serializable;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.repository.NoRepositoryBean;

/**

*

* @author Martins

*/

@NoRepositoryBean

public interface IBaseRepository extends JpaRepository {

void insert(T entity, ID id);

}

实现:自定义存储库基类.

注意:如果我沿着这条路线走下去,将会创建一个自定义异常类型.

import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.support.JpaEntityInformation;

import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import org.springframework.transaction.annotation.Transactional;

public class BaseRepositoryImpl

extends SimpleJpaRepository implements IBaseRepository {

private final EntityManager entityManager;

public BaseRepositoryImpl(Class domainClass, EntityManager em) {

super(domainClass, em);

this.entityManager = em;

}

public BaseRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {

super (entityInformation, entityManager);

this.entityManager = entityManager;

}

@Transactional

public void insert(T entity, ID id) {

T exists = entityManager.find(this.getDomainClass(),id);

if (exists == null) {

entityManager.persist(entity);

}

else

throw(new IllegalStateException("duplicate"));

}

}

自定义存储库工厂bean

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;

import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;

import org.springframework.data.repository.core.RepositoryMetadata;

import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;

import java.io.Serializable;

/**

* This factory bean replaces the default implementation of the repository interface

*/

public class BaseRepositoryFactoryBean, T, I extends Serializable>

extends JpaRepositoryFactoryBean {

protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

return new BaseRepositoryFactory(entityManager);

}

private static class BaseRepositoryFactory extends JpaRepositoryFactory {

private EntityManager entityManager;

public BaseRepositoryFactory(EntityManager entityManager) {

super(entityManager);

this.entityManager = entityManager;

}

protected Object getTargetRepository(RepositoryMetadata metadata) {

return new BaseRepositoryImpl((Class) metadata.getDomainType(), entityManager);

}

protected Class> getRepositoryBaseClass(RepositoryMetadata metadata) {

// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory

//to check for QueryDslJpaRepository's which is out of scope.

return IBaseRepository.class;

}

}

}

最后在配置中连接自定义存储库基类

// Define this class as a Spring configuration class

@Configuration

// Enable Spring/jpa transaction management.

@EnableTransactionManagement

@EnableJpaRepositories(basePackages = {"com.savant.test.spring.donorservicejpa.dao.repository"},

repositoryBaseClass = com.savant.test.spring.donorservicejpa.dao.repository.BaseRepositoryImpl.class)

可能的解决方案2

为实体实现Persistable接口并覆盖isNew()

用于管理回调方法以设置持久标志的基本实体类

import java.io.Serializable;

import javax.persistence.MappedSuperclass;

import javax.persistence.PostLoad;

import javax.persistence.PostPersist;

import javax.persistence.PostUpdate;

@MappedSuperclass

public abstract class BaseEntity implements Serializable{

protected transient boolean persisted;

@PostLoad

public void postLoad() {

this.persisted = true;

}

@PostUpdate

public void postUpdate() {

this.persisted = true;

}

@PostPersist

public void postPersist() {

this.persisted = true;

}

}

然后每个实体必须实现isNew()和getID()

import java.io.Serializable;

import javax.persistence.Column;

import javax.persistence.EmbeddedId;

import javax.persistence.Entity;

import javax.persistence.Table;

import javax.xml.bind.annotation.XmlRootElement;

import org.springframework.data.domain.Persistable;

@Entity

@Table(name = "MTHSEQ")

@XmlRootElement

public class Sequence extends BaseEntity implements Serializable, Persistable {

private static final long serialVersionUID = 1L;

@EmbeddedId

protected SequencePK sequencePK;

@Column(name = "NEXTSEQ")

private Integer nextseq;

public Sequence() {

}

@Override

public boolean isNew() {

return !persisted;

}

@Override

public SequencePK getId() {

return this.sequencePK;

}

public Sequence(SequencePK sequencePK) {

this.sequencePK = sequencePK;

}

public Sequence(String mthkey, Character centre) {

this.sequencePK = new SequencePK(mthkey, centre);

}

public SequencePK getSequencePK() {

return sequencePK;

}

public void setSequencePK(SequencePK sequencePK) {

this.sequencePK = sequencePK;

}

public Integer getNextseq() {

return nextseq;

}

public void setNextseq(Integer nextseq) {

this.nextseq = nextseq;

}

@Override

public int hashCode() {

int hash = 0;

hash += (sequencePK != null ? sequencePK.hashCode() : 0);

return hash;

}

@Override

public boolean equals(Object object) {

// TODO: Warning - this method won't work in the case the id fields are not set

if (!(object instanceof Sequence)) {

return false;

}

Sequence other = (Sequence) object;

if ((this.sequencePK == null && other.sequencePK != null) || (this.sequencePK != null && !this.sequencePK.equals(other.sequencePK))) {

return false;

}

return true;

}

@Override

public String toString() {

return "com.savant.test.spring.donorservice.core.entity.Sequence[ sequencePK=" + sequencePK + " ]";

}

}

抽象出isNew()会很好,但我认为不行. getId不能作为实体具有不同的Id,因为您可以看到这个具有复合PK.

java app的强制更新吗_java – Spring JPA / Hibernate事务强制插入而不是更新相关推荐

  1. Spring4.x(9)--Spring的Hibernate事务-XML

    Spring的Hibernate事务-XML 一.拷贝必要的jar包到工程的lib目录 二.创建spring的配置文件并导入约束 <?xml version="1.0" en ...

  2. spring.jpa.hibernate.naming.physical-strategy

    # Hibernate 5 物理命名策略类的全限定名 spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.na ...

  3. java实体中文字段_java - Spring JPA实体类是否可以包含不在数据库表中的非数据库字段 - SO中文参考 - www.soinside.com...

    我在SpringBoot中使用Spring JPA和Spring Data Rest.我有一个称为用户的数据库表和该表的实体.我没有此应用程序的控制器.@Entity @Table(name = &q ...

  4. (转载)spring配置hibernate 事务。

    Spring和Hibernate整合后,通过Hibernate API进行数据库操作时发现每次都要opensession,close,beginTransaction,commit,这些都是重复的工作 ...

  5. spring整合hibernate事务编程中错误分析

    2019独角兽企业重金招聘Python工程师标准>>> 在spring整合hibernate过程中,我们的配置文件: <?xml version="1.0" ...

  6. java collections.sort 忽略大小写排序_Java Spring Mongo排序忽略大小写问题

    我正在使用Spring-Data-mongodb对MongoDB执行各种请求. 尝试执行分页&时用忽略的情况排序我得到一个例外, 这是我的代码: Sort.Order order = new ...

  7. java什么是服务治理平台_Java | Spring Cloud 是如何实现服务治理的

    Spring Cloud 是如何实现服务治理的 Table of Contents 建议提前阅读 Spring Cloud Commons 之服务治理浅析 Spring 在设计的时候,通常会考虑方便扩 ...

  8. java里不支持post请求_java – Spring Boot – 不支持请求方法’POST’

    我的Spring Boot应用程序中不支持异常PageNotFound:Request方法'POST'. 这是我的控制器: @RestController public class LoginCont ...

  9. java中的repo什么意思_java – Spring数据jpa repo,为什么需要接口服务和服务实现

    我刚刚开始使用 Spring Data JPA开发Spring Boot.当我从表生成模型时,我创建了一个modelRepo,它扩展了JpaRepository< myModel,String& ...

最新文章

  1. xp 不能上传邮件附件的解决办法
  2. 三种SQL分页查询的存储过程
  3. Keras学习代码—github官网examples
  4. 一文带你全面了解电商在线支付
  5. Android ViewModel详解
  6. 国内MCU厂商也开始卷了
  7. java实现手机开关机_Android 系统重启与关机:Java 代码实现
  8. C#设计模式之单例模式
  9. JavaScript学习笔记:AJAX基础
  10. Swift 中的过滤器
  11. pyspark —— spark dataframe 从hdfs读写文件
  12. DOS那一代的程序员现在都干嘛呢
  13. 软件工程造价师和软件造价评估师有什么区别?
  14. android xml 设置半透明
  15. 在ubuntu上卸载anaconda
  16. Springboot整合Hibernate入门
  17. 用JAVA 创建自己的 A4 打印语言
  18. spring源码阅读笔记09:循环依赖
  19. 兔子数列 - C语言
  20. 千里走单骑:06-北京到上海骑记--Day5.风雨回家路

热门文章

  1. Anaconda3 | Ubuntu(python3.6)环境下安装opencv
  2. 《Deep Snake for Real-Time Instance Segmentation》
  3. 改善代码设计 —— 处理概括关系(Dealing with Generalization)
  4. (图论)51NOD 1298 圆与三角形
  5. 格式化文件系统命令所在目录——command not found
  6. Day14 字符编码
  7. C#多线程编程实战(二)
  8. [日常训练]training
  9. Nhibernate与Castle windsor (个人学习笔记1)
  10. Android 高级面试-2:IPC 相关