Я сталкиваюсь со следующей ошибкой в Hibernate: Обнаружено более одной строки с данным идентификатором , пока я пытаюсь объединить объект.
Подробности:
- Я использую Spring 2.5, Hibernate 3.2 и мое приложение, развернутое на Websphere ver 7.x
- Я применил сеанс БД для каждого HTTP-запросаметодология (не реализация весны), но я использовал ThreadLocal, чтобы сохранить сеанс для повторного использования в текущем HTTP-запросе, и как только ответ готов к отправке клиенту, у меня есть HTTPFilter, чтобы закрыть любой открытый сеанс в этом потоке.
- Я получил ошибку, когда у меня была массовая операция с БД в рамках одного HTTP-запроса (удаление, обновление, объединение, вставка, .....)
- Я использовал источник данных JNDIуправляемый самой Websphere
- Я думал примерно так: в начальной точке своего запроса я попросил фабрику сеансов предоставить мне экземпляр сеанса, и я использовал этот сеанс в своем запросе, пока не закрыл его вконец обработки моего запроса.и метод слияния hibernate пытается загрузить объект перед слиянием, после выполнения запроса на загрузку: выдается исключение, сообщающее, что (найдено более одной строки с данным идентификатором), для меня это означает, что объектперед загрузкой в текущий сеанс, поэтому первой глупой идеей было очистить и закрыть текущий сеанс перед объединением и начать новый только для этого объединения, я сделал это, но столкнулся с той же ошибкой, что означает, что я неправильно думал изначало.
- Второй подход, которому я пытаюсь следовать, состоит в том, чтобы разделить эту массовую операцию на несколько операций, выполняемых непосредственно в отдельном запросе ajax (предположим, у меня есть сетка с функциями обновления и удаления для каждой строки, я разрешаюПользователь обновляет и удаляет все, что он хочет, и я кеширую эти изменения до тех пор, пока пользователь не нажмет кнопку «Применить», чтобы применить все эти изменения. Новая идея: как только пользователь попытается удалить строку, новый запрос HTTP (с сеансом БД) будетнести ответственность за удаление этой строкив базе данных в этом случае больше не нужно нажимать кнопку «применить», поскольку изменения отражаются непосредственно в БД)
Структура БД (MS SQLServer 2008):
CREATE TABLE [dbo].[Correspondence_Site](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](500) NULL,
[Parent_Id] [int] NULL,
[Is_Active] [bit] NOT NULL,
[Dept_Id] [int] NULL, CONSTRAINT [PK_Correspondence_Sites] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
ALTER TABLE [dbo].[Correspondence_Site] WITH NOCHECK ADD CONSTRAINT [FK_Correspondence_Sites_Correspondence_Sites] FOREIGN KEY([Parent_Id]) REFERENCES [dbo].[Correspondence_Site] ([Id])
ALTER TABLE [dbo].[Correspondence_Site] CHECK CONSTRAINT [FK_Correspondence_Sites_Correspondence_Sites]
ALTER TABLE [dbo].[Correspondence_Site] ADD CONSTRAINT [DF_Correspondence_Site_Is_Active] DEFAULT ((1)) FOR [Is_Active]
CREATE TABLE [dbo].[Dep_Correspondence_Site](
[Department_Id] [int] NOT NULL,
[Correspondence_Site_Id] [int] NOT NULL,
[Serial] [varchar](50) NOT NULL,
[Site_Order] [int] NULL,
[Security_Level] [int] NULL) ON [PRIMARY]
ALTER TABLE [dbo].[Dep_Correspondence_Site] WITH NOCHECK ADD CONSTRAINT [FK__Dep_Correspondence_Sites_Correspondence_Sites] FOREIGN KEY([Correspondence_Site_Id]) REFERENCES [dbo].[Correspondence_Site] ([Id])
ALTER TABLE [dbo].[Dep_Correspondence_Site] CHECK CONSTRAINT [FK__Dep_Correspondence_Sites_Correspondence_Sites]
ALTER TABLE [dbo].[Dep_Correspondence_Site] WITH NOCHECK ADD CONSTRAINT [FK_Dep__Correspondence_Sites_Departments] FOREIGN KEY([Department_Id]) REFERENCES [dbo].[Department] ([Id])
CREATE TABLE [dbo].[Department](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](80) NOT NULL,
[Parent] [int] NULL,
[Type] [int] NOT NULL,
[Prefix] [varchar](100) NULL,
[Ldap_Prefix] [varchar](200) NULL,
[Serial_Prefix] [varchar](20) NULL,
[Manager_Id] [int] NULL,
[Assistant_Id] [int] NULL,
[Telephone_Numbers] [varchar](100) NULL,
[Fax_Numbers] [varchar](100) NULL,
[SMS_Max_Time] [int] NULL,
[Email_Max_Time] [int] NULL,
[Has_Correspondence] [bit] NULL,
[Email] [varchar](50) NULL,
[Logo_Image_Name] [varchar](50) NULL,
[Code] [int] NULL,
[Incoming_Fields] [int] NULL,
[Outgoing_Fields] [int] NULL,
[Internal_Memo_Fields] [int] NULL,
[Folder_Path] [nvarchar](200) NULL,
[Department_Last_Data_Update] [datetime] NULL,
CONSTRAINT [PK_Departments] PRIMARY KEY CLUSTERED ([Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
Эти три таблицы связаны следующим образом:
- Каждый отдел имеет 0..n корреспонденция_сайт
- Каждый корреспондент_сайт может быть подключен к 0..на отделу
- Таблица Dep_Correspondence_Site , позволяющая выполнить вышеуказанное отношение с некоторыми дополнительными полями, такими как (Serial, SecurityLevel, Order, ..)
Когда я сгенерировал отображение в спящем режиме,были сгенерированы следующие классы:
- Department.java, DepartmentDAO.java и Department.hbm.xml
- CorrespondenceSite.java, CorrespondenceSiteDAO.java и CorrespondenceSite.hbm.xml
- DepCorrespondenceSite.java, DepCorrespondenceSiteDAO.java, DepCorrespondenceSiteId.java, DepCorrespondenceSite.hbm.xml
The DepCorrespondenceSiteId является составным идентификатором.
DepCorrespondenceSiteId dcsID = new DepCorrespondenceSiteId();
dcsID.setDepartment(department);
dcsID.setCorrespondenceSite(fullCorrespondenceSite.mainCorrespondenceSite);
DepCorrespondenceSite dcs = new DepCorrespondenceSite();
dcs.setId(dcsID);
dcs.setSerial(fullCorrespondenceSite.mainCorrespondenceSite.getSerial());
dcs.setSiteOrder(new Integer(mainOrder));
dcs.setSecurityLevel(fullCorrespondenceSite.mainCorrespondenceSite.getSecurityLevel());
depCorrespondenceSiteDAO.update(dcs);
// Save sub correspondence site in database
for(CorrespondenceSite subCorrespondenceSite: fullCorrespondenceSite.subCorrespondenceSites){
dcsID = new DepCorrespondenceSiteId();
dcsID.setDepartment(department);
dcsID.setCorrespondenceSite(subCorrespondenceSite);
dcs = new DepCorrespondenceSite();
dcs.setId(dcsID);
dcs.setSerial(subCorrespondenceSite.getSerial());
dcs.setSecurityLevel(subCorrespondenceSite.getSecurityLevel());
dcs.setSiteOrder(new Integer(subOrder));
depCorrespondenceSiteDAO.update(dcs);
subOrder ++;
}
В цикле, и когда я пытался обновить dcs, я получил следующую ошибку (эта ошибка не для всех записей, некоторые записи обновляются правильно, и возникает исключение tдля четвертой записи, например)
[2/5/12 11:36:25:489 AST] 00000015 DefaultLoadEv I org.hibernate.event.def.DefaultLoadEventListener onLoad Error performing load command
org.hibernate.HibernateException: More than one row with the given identifier was found: com.ebla.moi.correspondence.model.entity.db.DepCorrespondenceSiteId@cc7f, for class: com.ebla.moi.correspondence.model.entity.db.DepCorrespondenceSite
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:69)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3044)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:395)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:179)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:229)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:120)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
at org.springframework.orm.hibernate3.HibernateTemplate$23.doInHibernate(HibernateTemplate.java:765)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:372)
at org.springframework.orm.hibernate3.HibernateTemplate.merge(HibernateTemplate.java:762)
at com.ebla.moi.correspondence.model.entity.db.DepCorrespondenceSiteDAO.update(DepCorrespondenceSiteDAO.java:56)
at com.ebla.moi.correspondence.view.bean.admin.departments.DepartmentVariablesBean.saveCorrespondenceSites(DepartmentVariablesBean.java:1438)
at com.ebla.moi.correspondence.view.bean.admin.departments.DepartmentVariablesBean.saveAdministration(DepartmentVariablesBean.java:1007)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.apache.el.parser.AstValue.invoke(AstValue.java:159)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:99)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:770)
at javax.faces.component.UICommand.broadcast(UICommand.java:372)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:458)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:763)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at com.icesoft.faces.webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:18)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.renderCycle(ReceiveSendUpdates.java:132)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.service(ReceiveSendUpdates.java:74)
at com.icesoft.faces.webapp.http.core.RequestVerifier.service(RequestVerifier.java:31)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.BasicAdaptingServlet.service(BasicAdaptingServlet.java:16)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:53)
at com.icesoft.faces.webapp.http.servlet.SessionVerifier.service(SessionVerifier.java:26)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:131)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1657)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1597)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:131)
at com.ebla.moi.correspondence.util.filters.CharsetFilter.doFilter(CharsetFilter.java:28)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:188)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:116)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:77)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:908)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:934)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:502)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:179)
at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:91)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:864)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:445)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:504)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:301)
at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)
Функция обновления в DepCorrespondenceSiteDAO.java:
public void update(DepCorrespondenceSite transientInstance){
log.debug("updating DepCorrespondenceSite instance");
try {
if(transientInstance.getId() != null){
getMyHibernateTemplate().merge(transientInstance);
}else{
getMyHibernateTemplate().saveOrUpdate(transientInstance);
}
log.debug("update successful");
} catch (RuntimeException re) {
log.error("update failed", re);
throw re;
}
}
DepCorrespondenceSiteId.java
public class DepCorrespondenceSiteId implements java.io.Serializable {
private Department department;
private CorrespondenceSite correspondenceSite;
public DepCorrespondenceSiteId() {
}
public DepCorrespondenceSiteId(Department department,
CorrespondenceSite correspondenceSite) {
this.department = department;
this.correspondenceSite = correspondenceSite;
}
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
public CorrespondenceSite getCorrespondenceSite() {
return this.correspondenceSite;
}
public void setCorrespondenceSite(CorrespondenceSite correspondenceSite) {
this.correspondenceSite = correspondenceSite;
}
}
Пожалуйста, помогитемне.С уважением