學術討論會(縮短) -重複的關鍵問題 - 需要援助
我有一個加載從相應的DAO一個配置文件對象的控制器。它更新了一些屬性,其中許多屬性集,然後調用saveOrUpdate(通過保存在DAO中)來重新附加和更新配置文件對象。以看似隨機的間隔,我們得到一個org.hibernate.exception.ConstraintViolationException,其根本原因是:由於:java.sql.BatchUpdateException:對於鍵1重複條目'3-56'。堆棧跟蹤指向調用的saveOrUpdate方法從配置文件更新控制器。我不能在我的測試環境中複製,我們只在生產環境中看到這一點,所以我想知道是否缺少與線程安全相關的東西(這就是爲什麼我發佈了太多代碼/配置信息)。有任何想法嗎?
- 代碼 -
我試圖提供儘可能多的相關配置/代碼可能 - 讓我知道,如果需要更多:
這裏是有問題的控制器的摘錄:
public class EditProfileController extends SimpleFormController {
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception
{
if(!checkLoggedIn(request))
{
return new ModelAndView("redirect:" + invalidRedirect);
}
HttpSession session = request.getSession();
Resource resource = (Resource)session.getAttribute("resource"); //The resource object is stored in session upon login and upon account creation.
Profile profile = profiles.getProfileByResource(resource);
if(profile == null)
{
profile = new Profile();
profile.setResource(resource);
}
//I use custom editors to populate the sets in the command object with objects based on the selection
if(profile.getPrimaryRoleSkills() != null && editProfileCommand.getPrimaryRoleSkills() != null)
{
profile.getPrimaryRoleSkills().addAll(editProfileCommand.getPrimaryRoleSkills());
profile.getPrimaryRoleSkills().retainAll(editProfileCommand.getPrimaryRoleSkills());
}
else
profile.setPrimaryRoleSkills(editProfileCommand.getPrimaryRoleSkills());
profiles.save(profile); //This is the line that appears in the stack trace
return new ModelAndView(getSuccessView());
}
//Other methods omitted
}
縮Profile類:
public class Profile implements java.io.Serializable {
private long id;
private Resource resource;
private Set<PrimaryRoleSkill> primaryRoleSkills = new HashSet<PrimaryRoleSkill>(0);
public Profile() {
}
//Other properties trivial or similar to above. Getters and setters omitted
//toString, equals, and hashCode are all generated by hbm2java
}
namevaluepairs中淺E類(PrimaryRoleSkill擴展了這種不添加任何東西):
public class NameValuePairs implements java.io.Serializable {
private long id;
private String name;
private boolean active = true;
public NameValuePairs() {
}
//equals and hashCode generated by hbm2java, getters & setters omitted
}
這裏是我的DAO基類:
public class DAO {
protected DAO() {
}
public static Session getSession() {
Session session = (Session) DAO.session.get();
if (session == null) {
session = sessionFactory.openSession();
DAO.session.set(session);
}
return session;
}
protected void begin() {
getSession().beginTransaction();
}
protected void commit() {
getSession().getTransaction().commit();
}
protected void rollback() {
try {
getSession().getTransaction().rollback();
} catch(HibernateException e) {
log.log(Level.WARNING,"Cannot rollback",e);
}
try {
getSession().close();
} catch(HibernateException e) {
log.log(Level.WARNING,"Cannot close",e);
}
DAO.session.set(null);
}
public boolean save(Object object)
{
try {
begin();
getSession().saveOrUpdate(object);
commit();
return true;
}
catch (HibernateException e) {
log.log(Level.WARNING,"Cannot save",e);
rollback();
return false;
}
}
private static final ThreadLocal<Session> session = new ThreadLocal<Session>();
private static final SessionFactory sessionFactory = new Configuration()
.configure().buildSessionFactory();
private static final Logger log = Logger.getAnonymousLogger();
//Non-related methods omitted.
}
下面是簡介DAO的重要組成部分:
public class Profiles extends DAO {
public Profile getProfileByResource(Resource resource)
{
try
{
begin();
Query q = getSession().createQuery("from Profile where resource = :resource");
q.setLong("resource", resource.getId());
commit();
if(q.uniqueResult() == null)
return null;
return (Profile) q.uniqueResult();
}
catch(HibernateException e)
{
rollback();
}
return null;
}
//Non-related methods omitted.
}
相關彈簧配置:
<bean id="profiles" class="com.xxxx.dao.Profiles" />
<bean id="editProfileController" class="com.xxxx.controllers.EditProfileController">
<property name="sessionForm" value="false" />
<property name="commandName" value="editProfileCommand" />
<property name="commandClass" value="com.xxxx.commands.EditProfileCommand" />
<property name="profiles" ref="profiles" />
<property name="formView" value="EditProfile" />
<property name="successView" value="redirect:/profile" />
<property name="validator" ref="profileValidator" />
</bean>
的hibernate.cfg.xml
<session-factory>
<property name="connection.driver_class">@[email protected]</property>
<property name="connection.url">@[email protected]</property>
<property name="connection.username">@[email protected]</property>
<property name="connection.password">@[email protected]</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="dbcp.maxActive">15</property>
<property name="dbcp.maxIdle">5</property>
<property name="dbcp.maxWait">120000</property>
<property name="dbcp.whenExhaustedAction">2</property>
<property name="dbcp.testOnBorrow">true</property>
<property name="dbcp.testOnReturn">true</property>
<property name="dbcp.validationQuery">
select 1
</property>
<property name="dbcp.ps.maxActive">0</property>
<property name="dbcp.ps.maxIdle">0</property>
<property name="dbcp.ps.maxWait">-1</property>
<property name="dbcp.ps.whenExhaustedAction">2</property>
<!-- Echo all executed SQL to stdout
<property name="show_sql">true</property>
-->
<mapping resource="com/xxxx/entity/Resource.hbm.xml"/>
<mapping resource="com/xxxx/entity/Authentication.hbm.xml"/>
<mapping resource="com/xxxx/entity/NameValuePairs.hbm.xml"/>
<mapping resource="com/xxxx/entity/Profile.hbm.xml"/>
<mapping resource="com/xxxx/entity/FileData.hbm.xml"/>
</session-factory>
從Profile.hbm.xml摘錄:從NameValuePairs.hbm.xml
<hibernate-mapping>
<class name="com.xxxx.entity.Profile" select-before-update="true">
<id name="id" type="long">
<generator class="foreign">
<param name="property">resource</param>
</generator>
</id>
<set name="primaryRoleSkills" cascade="none">
<key column="profile"/>
<many-to-many column="primary_role_skill" class="com.xxxx.entity.PrimaryRoleSkill"/>
</set>
</class>
</hibernate-mapping>
摘錄:
<hibernate-mapping>
<class name="com.xxxx.entity.NameValuePairs" abstract="true">
<id name="id" type="long">
<generator class="native" />
</id>
<discriminator column="type" type="string" />
<property type="string" name="name" length="256">
<meta attribute="use-in-equals">true</meta>
</property>
<property type="boolean" name="active">
<meta attribute="default-value">true</meta>
</property>
<subclass name="com.xxxx.entity.PrimaryRoleSkill" discriminator-value="PrimaryRoleSkill" />
</class>
</hibernate-mapping>
中的應用在Tomcat 6.0.14上運行,並連接到在Linux上運行的MySQL版本5.0.89社區。我們使用Hibernate 3.3.2和Spring Framework 2.5.6。
嘗試只包括相關信息。它是太長的閱讀.. – Bozho
請參閱http://sscce.org/ – Bozho
你的DAO不應該啓動/提交/管理事務 - 業務對象(服務)應該。 – les2