为什么Oracle / Java在一个执行中创建多个记录? [英] Why does Oracle/Java creates multiple records in one execution?

查看:129
本文介绍了为什么Oracle / Java在一个执行中创建多个记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在调试一个基于java的Web应用程序。我们的生产
环境中报告了一个问题,表中插入了多个记录,但其他记录无效



生产问题结果: / strong>



标题表

HDR_NO  HDR_COL1  HDR_COL1  DOCUMENT_DATE

HDR44&emsp ;        6/6/2014 14:22

HDR45      327     6/6/2014 14:24 - 无效数据

HDR46        / 6/2014 14:24 - 无效资料



详细资料表



DTL_NO  HDR_NO  DTL_COL1  DTL_COL1

DTL76   HDR44   SR1439   4337

DTL77    SR1439   4337 - 无效数据

DTL78   HDR37 无效数据



生产问题结果:



预期结果:每个表只有一个记录)。


我试过通过发送三个连续的httpservlet请求来在我的本地环境中复制此问题。

在我们的验证中,两个请求被过滤,因为它将尝试插入

头的三个实例,同一个HDR_NO id。

在我的测试中为每个表插入一个记录。我现在的问题是,是什么导致这个错误?

我的代码看起来像下面的代码。请帮助。

提前感谢

  public class MyController extends SimpleFormController {
public ModelAndView onSubmit(HttpServletRequest request,HttpServletResponse response,Object
private MyService myService
command,BindException errors){
BeanParam bean = buildBeanParam(request);
myService.doTransaction(bean);
}
}
public class MyService {
public void doTransaction(BeanParam bean){
try {
List item items = getItems(bean) / query with一个结果
Header header = createHeader(); //神秘的bug发生
populateDetails(header,items); //神秘的bug发生
} catch(GenerateIdException e){
e.printStackTrace();
}
}
public Header createHeader(){
Header header = new Header();
//生成一个带有公共前缀的数字
header.setHeaderNo(headerNumberGenerator());
header.setDocumentDate(new Date());
header.setHdrcol1(String 1);
header.setHdrcol2(String 2);
return headerDao.save(header);
}
public void populateDetails(Header header,List; Item; items){
for(Item item:items){
//items.size()== 1,因此详细信息表中的一个记录是预期的
详细信息= new Detail();
//生成一个带有公共前缀的数字
detail.setDetailNo(detailNumberGenerator());
detail.setDocumentDate(new Date());
detail.setDtlcol1(item.getField1());
detail.setDtlcol2(item.getField2());
detail.setHeader(header);
detailDao.save(detail);
}
}
}

public class Header {
@Id
@Column(name =HDR_NO,length = 20)
private String headerNo;

@Temporal(TemporalType.DATE)
@Column(name =DOCUMENT_DATE)
private Date documentDate;

@Column(name =HDR_COL1)
private String hdrcol1;

@Column(name =HDR_COL2)
private String hdrcol2;

@OneToMany(mappedBy =header)
@Cascade(value = {CascadeType.PERSIST,CascadeType.MERGE})
private List Details details;
// Getters和Setters
}
public class Details {
@Id
@Column(name =DTL_NO)
private String detailNo;

@ManyToOne
@JoinColumn(name =HDR_NO,referencedColumnName =HDR_NO)
private头部头;

@Column(name =DTL_COL1)
private String dtlcol1;

@Column(name =DTL_COL2)
private String dtlcol2;
// Getters和Setters
}
public class Item {
@Column(name =FIELD1)
private field1;
@Column(name =FIELD2)
private field2;
// Getters and Setters
}


解决方案

您的问题不清楚您如何执行验证,但由于数据库允许重复,它表明验证是在应用程序层完成,并且没有主/唯一键约束。



自己做验证的麻烦是你在运行SELECT之前检查存在的时间,以及当你INSERT,别人没有snook,插入?可能只有几毫秒的差异,这就是为什么它将很难复制。


I'm debugging a java based web application. There is an issue reported from our production environment where multiple records were inserted in table, but other records was not valid

Production issue results:

Header Table

HDR_NO HDR_COL1 HDR_COL1 DOCUMENT_DATE
HDR44  68     327    6/6/2014 14:22
HDR45  68     327    6/6/2014 14:24--invalid data
HDR46  68     327    6/6/2014 14:24--invalid data

Detail Table

DTL_NO HDR_NO DTL_COL1 DTL_COL1
DTL76  HDR44  SR1439  4337
DTL77  HDR45  SR1439  4337--invalid data
DTL78  HDR46  SR1439  4337--invalid data

Production issue results:

(expected result: Only one record for each table).

I tried to replicate this issue in my local environment by sending three consecutive httpservletrequest.
Two requests were filtered in our validations, because it will try to insert three instance of
header with same HDR_NO as id.
One record inserted for each table in my testing. My question now is, what caused this bug?
My code looks like the code below. Please help.
Thanks in advance,

public class MyController extends SimpleFormController{
    public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response,Object
    private MyService myService
    command, BindException errors){
        BeanParam bean = buildBeanParam(request);
        myService.doTransaction(bean);
    }
}
public class MyService{
    public void doTransaction(BeanParam bean){
        try{
            List Item items = getItems(bean);// query with one result
            Header header = createHeader();//mysterious bug occur
            populateDetails(header, items);//mysterious bug occur
            } catch (GenerateIdException e) {
            e.printStackTrace();
        }
    }
    public Header createHeader(){
        Header header = new Header();
        // generates a number with common prefix
        header.setHeaderNo(headerNumberGenerator());
        header.setDocumentDate(new Date());
        header.setHdrcol1("String 1");
        header.setHdrcol2("String 2");
        return headerDao.save(header);
    }
    public void populateDetails(Header header, List;Item; items){
        for(Item item: items){
            //items.size() == 1, so one record in Detail Table is expected
            Detail detail = new Detail();
            // generates a number with common prefix
            detail.setDetailNo(detailNumberGenerator());
            detail.setDocumentDate(new Date());
            detail.setDtlcol1(item.getField1());
            detail.setDtlcol2(item.getField2());
            detail.setHeader(header);
            detailDao.save(detail);
        }
    }
}

public class Header{
    @Id
    @Column(name = "HDR_NO", length = 20)
    private String headerNo;

    @Temporal(TemporalType.DATE)
    @Column(name = "DOCUMENT_DATE")
    private Date documentDate;

    @Column(name = "HDR_COL1")
    private String hdrcol1;

    @Column(name = "HDR_COL2")
    private String hdrcol2;

    @OneToMany(mappedBy = "header")
    @Cascade(value = { CascadeType.PERSIST, CascadeType.MERGE })
    private List Details details;
    //Getters and Setters
}
public class Details{
    @Id
    @Column(name = "DTL_NO")
    private String detailNo;

    @ManyToOne
    @JoinColumn(name = "HDR_NO", referencedColumnName = "HDR_NO")
    private Header header;

    @Column(name = "DTL_COL1")
    private String dtlcol1;

    @Column(name = "DTL_COL2")
    private String dtlcol2;
    //Getters and Setters
}
public class Item{
    @Column(name = "FIELD1")
    private field1;
    @Column(name = "FIELD2")
    private field2;
    //Getters and Setters
}

解决方案

It's not clear in your question how you are doing the "validation", but since the database allows duplicates it suggests that the validation is being done in the app layer, and that there are no primary/unique key constraints.

The trouble with doing with validation yourself is how do you that between the time you ran a SELECT to check for existence and when you INSERT, that someone else hasn't snook in and inserted? May only be a few milliseconds difference, which is why it will be difficult to replicate.

这篇关于为什么Oracle / Java在一个执行中创建多个记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆