为什么Oracle / Java在一个执行中创建多个记录? [英] Why does Oracle/Java creates multiple records in one execution?
问题描述
我正在调试一个基于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屋!