Why does Oracle/Java creates multiple records in one execution?

半城伤御伤魂 提交于 2020-01-03 05:10:07

问题


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
}

回答1:


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.



来源:https://stackoverflow.com/questions/24626103/why-does-oracle-java-creates-multiple-records-in-one-execution

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!