【发布时间】:2013-06-18 04:56:09
【问题描述】:
我有一个具有以下字段的类:
@Version
private Long version = 1L;
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
我使用 Spring web + Hibernate。希望能看到一个比较完整的例子,使用@Version 防止同时编辑同一条记录。
用 Google 搜索并搜索了 SO。找不到任何东西。我为版本字段使用了一个隐藏的 HTML 表单字段,但它不起作用。
非常感谢任何信息/指针。
感谢和问候!
更新 1
这就是我所做的。我在两个浏览器窗口中加载了相同的记录。我能够看到在两个窗口的 HTML 表单中有一个隐藏的版本字段具有相同的值。我在一个窗口中提交了表单并检查了数据库,发现版本字段增加了。然后我提交了另一个窗口。什么也没发生,记录已成功更新/保存。我期待会引发某种异常。
除了 Version 字段定义之外,我还需要配置 spring/hibernate 组合以使其工作吗?
更新 2
我做了以下跟踪 Hibernate 如何更新记录:
hibernate.show_sql=true
log4j.logger.org.hibernate.type=trace
现在我可以看到 Hibernate 如何更新记录了。我注意到在 Hibernate 使用以下 SQL 更新记录时
update ... where id=? and version=?
Hibernate 总是使用数据库中的最新版本号进行绑定,即使我可以确认在 web 层中的记录在保存记录之前仍然具有旧版本号以及带有新数据的其他字段。
怎么会?
我觉得我的应用程序以某种方式禁用了乐观锁定,但我没有为此进行 Hibernate 配置。我正在使用 Hibernate 4.2.1.Final 和 Spring 3.2.2.RELEASE。
有没有办法显式启用/禁用 Hibernate 乐观锁定?
更新 3
以下是数据对象和数据库层代码。 “friendGroupDao”自动连接到事务服务层,在该层调用此 DAO 对象以将对象加载到 Web 层并将对象保存到数据库。相关的服务层方法只需调用friendGroupDao.load()和friendGroupDao.save(),无需任何额外代码。
------------- 域对象 -------------
@MappedSuperclass
public abstract class BaseObject implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Version
private Long version = 1L;
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public BaseObject() {
}
}
@Entity
public class FriendGroup extends BaseObject {
@Column(columnDefinition = "NVARCHAR(120)")
private String name;
public String getName() {
return name;
}
public void setName(String accountName) {
this.name = accountName;
}
}
--------------- database -------------
public interface BaseObjectDao<T extends BaseObject> {
void delete(T o);
T load(Long id);
void save(T o);
}
public class BaseObjectDaoImpl<T extends BaseObject> implements
BaseObjectDao<T> {
private Class<T> domainClass;
@Autowired
protected SessionFactory sessionFactory;
public BaseObjectDaoImpl() {
this.domainClass = (Class<T>) BaseObject.class;
}
public BaseObjectDaoImpl(Class<T> domainClass) {
this.domainClass = domainClass;
}
public SessionFactory getSessFactory() {
return sessionFactory;
}
public void setSessFactory(SessionFactory sf) {
this.sessionFactory = sf;
}
public void delete(T object) {
getSession().delete(object);
}
public T load(Long id) {
return (T) getSession().get(domainClass, id);
}
public void save(T object) {
getSession().saveOrUpdate(object);
}
public Session getSession() {
return sessionFactory.getCurrentSession();
}
}
public interface FriendGroupDao extends BaseObjectDao<FriendGroup> {
}
@Repository("friendGroupDao")
public class FriendGroupDaoImpl extends BaseObjectDaoImpl<FriendGroup> implements
FriendGroupDao {
public FriendGroupDaoImpl() {
super(FriendGroup.class);
}
}
【问题讨论】:
-
“它不工作”是什么意思?您期待什么以及会发生什么?
-
andih,我在发帖之前阅读了第一篇文章。第二个帖子很有帮助。这可能是我发这个帖子的原因。我不确定它是如何工作的。
-
默认启用乐观锁定支持。肯定有一个异常被抛出,但可能没有记录。您应该尝试使用调试器运行此事务以查看会发生什么。还可以尝试打印 Hibernate 发送的所有 SQL 查询(hibernate.show_sql = true)。
-
Spiff,我听从了你的建议。仍然得到了神秘的结果。请参阅我更新的帖子。谢谢!