假设我有一张这样的表
USER_ID USERNAME PASSWORD DATE_CREATED DATE_LAST_LOGIN
1 'user1' 'password1' '12-Jun-2010' '12-Nov-2010'
2 'user2' 'password2' '14-Jun-2010' '12-Nov-2010'
使用hibernate映射到POJO类
@Entity
@Table( name="user" )
public class User {
private Integer id;
private String username;
private String password;
private Date dateCreated;
private Date dateLastLogin;
public User() {
}
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
public IntegergetId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Colum( name="USERNAME" )
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Colum( name="PASSWORD" )
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password= password;
}
@Colum( name="DATE_CREATED" )
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated= dateCreated;
}
@Colum( name="DATE_LAST_LOGIN" )
public Date getDateLastLogin() {
return dateLastLogin;
}
public void setDateLastLogin(Date dateLastLogin) {
this.dateLastLogin = dateLastLogin;
}
}
本课程将以两种方式使用, 1.验证用户是否登录,当用户登录时,将使用当前日期更新DATE_LAST_LOGIN。 2.在用户编辑表单中更新用户详细信息。
我的问题是我只想在用户登录时更新DATE_LAST_LOGIN字段,而不是在表单中编辑用户时。如果我要加载一个用户记录,然后在不调用setDateLastLogin的情况下保存它,那么在用户登录加载和更新操作之前,这将是正常的。这将导致在db中更新DATE_LAST_LOGIN,但是当用户编辑表单保存更改时,它将使用旧的不正确的值覆盖DATE_LAST_LOGIN。
编辑:
我认为我没有完全解释这种情况,所以这里有更多信息....这是特别在webapp中,用户的更新就是这样。
我认为在更新表单提交之前不再从数据库中查询对象,我只是使用表单中的字段填充新对象并将其保存到数据库,这当然意味着dateLastLogin为null在保存更新时,因此将在DB中用null替换正确的值。这显然无法通过简单地同步线程来解决。在休眠之前,我只是选择不更新DATE_LAST_LOGIN字段,但是hibernate不允许我做出设计时间决定。
另一种方法是在用表单中的字段覆盖之前查询对象,但是这迫使我必须在更新之前运行查询,如果没有hibernate,我不必这样做,这会迫使我使用在一个答案中建议的同步。问题是同步只适用于当前的应用程序,如果我有多个应用程序更新同一个数据库,那么它就没用了。
回到我原来的问题,有没有办法从更新中排除字段,如果不是简单地要求hibernate这样做,那么可能是由不同的系统设计。
答案 0 :(得分:1)
这是一个比Hibernate更多的同步问题。您应该使两个操作(用户的登录和版本)相互原子化。这可以通过简单的Java同步(在进入这些操作Java方法之前使用常见的互斥锁或锁)或通过数据库(即Hibernate)事务管理来实现。
答案 1 :(得分:1)
我的建议是为用户使用2个不同的实体,例如: User
和UserLogin
(后者会扩展常规User
并保留dateLastLogin
属性)并在身份验证期间使用UserLogin
并使用User
编辑用户详细信息时。
答案 2 :(得分:0)
您可以使用切换(布尔值)控制此值,您可以根据需要切换,然后将此检查添加到设置器中吗?
例如:
boolean dateLastLoginUpdatable = false;
public void setDateLastLogin(Date dateLastLogin) {
if( dateLastLoginUpdatable ) {
this.dateLastLogin = dateLastLogin;
}
}
public void toggleLastLoginEditable( boolean newValue ) {
dateLastLoginUpdatable = newValue;
}
答案 3 :(得分:0)
好的,所以我提出了自己的解决方案,虽然我不知道目前是否有更好的解决方案,但仍然适用于我。
基本上在我的POJO中,我通过向注释中添加updatable = false来读取getDateLastLogin字段,如此
@Colum( name="DATE_LAST_LOGIN", updatable = false )
public Date getDateLastLogin() {
return dateLastLogin;
}
然后在登录时我绕过POJO并直接使用我的登录控制器中的HQL更新更新数据库
public void login(String username, String password) {
User user = getUser( username, password );
if( user != null ) {
Query userUpdate = getSession().createQuery( "update User set dateLastLogin = current_timestamp where id = :userId" );
userUpdate.setInteger( "userId", user.getId() );
userUpdate.executeUpdate();
}
}