Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 具有插入或更新机制的Spring批处理自定义itemWriter_Database_Spring_Jpa_Spring Batch_Upsert - Fatal编程技术网

Database 具有插入或更新机制的Spring批处理自定义itemWriter

Database 具有插入或更新机制的Spring批处理自定义itemWriter,database,spring,jpa,spring-batch,upsert,Database,Spring,Jpa,Spring Batch,Upsert,我有一个带有基本块的Spring批处理: 读取CSV文件 处理它(将一些编码值转换成另一个) 将结果写入数据库 问题 在某些情况下,我希望在我的自定义ItemWriter中插入或更新机制 示例:我可以在我的CSV C006;Test;OK;01/01/1970;1 C006;Test;OK;01/01/1970;5 您可以发现,除了最后一列之外,它们非常相似,策略如下: 如果我有一个“类似”实体,请检查数据库 如果为true,则使用您获得的最后一项更新该值(在本例中,第二行最后一列中的值为5)

我有一个带有基本块的
Spring批处理

  • 读取CSV文件
  • 处理它(将一些编码值转换成另一个)
  • 将结果写入数据库
  • 问题

    在某些情况下,我希望在我的自定义
    ItemWriter
    中插入或更新机制

    示例:我可以在我的
    CSV

    C006;Test;OK;01/01/1970;1
    C006;Test;OK;01/01/1970;5
    
    您可以发现,除了最后一列之外,它们非常相似,策略如下:

  • 如果我有一个“类似”实体,请检查数据库
  • 如果为true,则使用您获得的最后一项更新该值(在本例中,第二行最后一列中的值为5)
  • 我已经做了什么?

    @Embeddable
    public class CarPK implements Serializable {
    
        @Column
        private String chassisSerialNumber;
    
        @Column
        private String engineSerialNumber;
    
        public CarPK(){
            // Your class must have a no-arq constructor
        }
    
        @Override
        public boolean equals(Object obj) {
            if(obj instanceof CarPK){
                CarPK carPk = (CarPK) obj;
    
                if(!carPk.getChassisSerialNumber().equals(chassisSerialNumber)){
                    return false;
                }
    
                if(!carPk.getEngineSerialNumber().equals(engineSerialNumber)){
                    return false;
                }
    
                return true;
            }
    
            return false;
        }
    
        @Override
        public int hashCode() {
            return chassisSerialNumber.hashCode() + engineSerialNumber.hashCode();
        }
    
        //setter and getter
    }
    
    在我的实体bean中,我添加了一个唯一的约束Anotion,如下所示:

    @Table(name = "indicator",
        uniqueConstraints = { @UniqueConstraint(columnNames = 
                                            { "reference", "type", "status", "date" }) })
    
    现在我可以肯定,我不能用同一列的数据持久化一个实体。然后,我创建了一个自定义的
    ItemWriter
    ,我试图捕获ConstraintViolationException,但它不起作用,我总是得到一个其他的exeption,即使我尝试了父exeption

    那么你有什么想法或其他方法来做吗

    我在考虑使用合并JPA功能?你觉得怎么样

    我的自定义ItemWriter

    @Component
    public class ImportItemWriter implements ItemWriter<Indicator>{
    
        @Autowired
        protected IndicatorDao indicatorDao;
    
        public void write(List<? extends Indicator> items) throws Exception {
    
            for (Indicator item : items) {
                Indicator indicator = new Indicator();
    
                indicator.setReference(item.getReference());
                indicator.setType(item.getType());
                indicator.setStatus(item.getStatus());
                indicator.setDueDate(item.getDueDate());
    
                indicator.setValue(item.getValue());
    
                try {
                    indicatorDao.persist(indicator);
                } catch (ConstraintViolationException e) {
                    // TODO: handle exception
                }       
            }
        }
    }
    

    一个选项是使用分类复合编写器。
    分类器
    将用于确定是执行插入还是更新。然后您需要配置两个委托,一个用于插入,一个用于更新。

    总结上述评论。

    你想过直接使用吗。。该实现执行entityManger.merge(。。如果您的实体有一个复合pkey,您可以用这种方法求解

        <job id="writeProductsJob" xmlns="http://www.springframework.org/schema/batch">
            <step id="readWrite">
                <tasklet>
                    <chunk reader="productItemReader" writer="productItemWriter" commit-interval="3" />
                </tasklet>
            </step>
        </job>
    
        <bean id="productItemWriter" class="org.springframework.batch.item.database.JpaItemWriter">
            <property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean>
    
    复合主键

    @Embeddable
    public class CarPK implements Serializable {
    
        @Column
        private String chassisSerialNumber;
    
        @Column
        private String engineSerialNumber;
    
        public CarPK(){
            // Your class must have a no-arq constructor
        }
    
        @Override
        public boolean equals(Object obj) {
            if(obj instanceof CarPK){
                CarPK carPk = (CarPK) obj;
    
                if(!carPk.getChassisSerialNumber().equals(chassisSerialNumber)){
                    return false;
                }
    
                if(!carPk.getEngineSerialNumber().equals(engineSerialNumber)){
                    return false;
                }
    
                return true;
            }
    
            return false;
        }
    
        @Override
        public int hashCode() {
            return chassisSerialNumber.hashCode() + engineSerialNumber.hashCode();
        }
    
        //setter and getter
    }
    

    你想过直接使用吗。。该实现执行entityManger.merge(。。如果你的实体有一个复合pkey,你可以用这种方法来解决。是的,我以前使用过JpaItemWriter,但不起作用,我想合并只捕获主键,在我的情况下,我不关心它,我有一个特定的目的,同时检查4个属性你可以用4个属性创建一个复合主键:)。。但是如果你不能改变你的实体,那么你的“ImportItemWriter”也是一样的吗如果要创建复合主键,我将尝试一下。谢谢你解决了这个问题吗?如果是,您是如何解决的?这并没有解决捕获是否必须插入或更新的问题。此解决方案没有解决您需求的哪些部分?使用分类器的想法一点也不坏,但在我的情况下,我还有另一个问题。基本上,我希望找到一种机制,使我能够确定是否需要更新或插入项目。然后,插入或更新不是问题,但首先我需要了解情况。谢谢;)好主意,我以前不知道有类似复合Pkey的东西!但是在测试之前,从概念上讲,创建一个包含9个参数的复合pkey的实体是好的吗?如果每个字段的集合在数据库中必须是唯一的,我认为从概念上讲是正确的。是上帝的方式,也是因为它是由ORM处理的。无论是否为复合密钥,JPA都不会对性能产生显著影响。
    @Embeddable
    public class CarPK implements Serializable {
    
        @Column
        private String chassisSerialNumber;
    
        @Column
        private String engineSerialNumber;
    
        public CarPK(){
            // Your class must have a no-arq constructor
        }
    
        @Override
        public boolean equals(Object obj) {
            if(obj instanceof CarPK){
                CarPK carPk = (CarPK) obj;
    
                if(!carPk.getChassisSerialNumber().equals(chassisSerialNumber)){
                    return false;
                }
    
                if(!carPk.getEngineSerialNumber().equals(engineSerialNumber)){
                    return false;
                }
    
                return true;
            }
    
            return false;
        }
    
        @Override
        public int hashCode() {
            return chassisSerialNumber.hashCode() + engineSerialNumber.hashCode();
        }
    
        //setter and getter
    }