基於 RBAC 思想簡化:
isDeleted 標記三張核心表:users、roles、groups,加中間表 users_groups(含 status 審批狀態)。
@Entity @Table(name='users') @Undeletable(status='isDeleted')
public class User implements Serializable {
@Id @GeneratedValue(strategy=GenerationType.AUTO) Integer id;
String name, password, monicker, question, answer, email, qq;
@ManyToOne @JoinColumn(name='roleid') Role role;
@Column(name='score', insertable=false) Integer score;
@Column(name='regtime', insertable=false) @Temporal(TemporalType.TIMESTAMP) Date regTime;
@Column(name='logintime', insertable=false) @Temporal(TemporalType.TIMESTAMP) Date loginTime;
@Column(name='isdeleted', insertable=false) Byte isDeleted;
@ManyToMany(targetEntity=Group.class, cascade={PERSIST, MERGE})
@JoinTable(name='users_groups',
joinColumns=@JoinColumn(name='userid'),
inverseJoinColumns=@JoinColumn(name='groupid'))
List<Group> groups;
// getters/setters
}
關鍵點:
@Table(name='users') 解決實體類單複數不一致@Undeletable 配合 SpringSide HibernateEntityExtendDao 實現軟刪除insertable=false 讓 DB 默認值生效(timestamp、isDeleted)@Temporal(TIMESTAMP) 映射 MySQL timestamp(建議用 java.util.Date,避免 java.sql.Timestamp 毫微秒浪費)@ManyToOne + @JoinColumn 定義多對一,User 為主控方@ManyToMany + @JoinTable 定義多對多,User 為主控方@Entity @Table(name='roles')
public class Role implements Serializable {
@Id @GeneratedValue Integer id;
String name, privilegesFlag; // getters/setters
}
@Entity @Table(name='groups') @Undeletable(status='isDeleted')
public class Group implements Serializable {
@Id @GeneratedValue Integer id;
String name;
@ManyToOne(cascade={PERSIST, MERGE}) @JoinColumn(name='creatorid') User creator;
@Column(name='createtime', insertable=false) @Temporal(TemporalType.TIMESTAMP) Date createTime;
@Column(name='isdeleted', insertable=false) String isDeleted;
@ManyToMany(cascade={PERSIST, MERGE}, mappedBy='groups', targetEntity=User.class)
List<User> users; // 被控方,mappedBy 指向 User.groups
}
雙向關聯:User 為主控方,Group 端用 mappedBy。同時 Group→User (creator) 為單向多對一。
三個 Manager 繼承 HibernateEntityExtendDao<T>:
public class UserManager extends HibernateEntityExtendDao<User> {}
public class RoleManager extends HibernateEntityExtendDao<Role> {}
public class GroupManager extends HibernateEntityExtendDao<Group> {}
hibernate.cfg.xml 註冊實體類;serviceContext.xml 交給 Spring 管理(byName 自動注入)。
applicationContext.xml AOP 事務切面:
<aop:config proxy-target-class='true'>
<aop:advisor pointcut='execution(* *..manager.*Manager.*(..))' advice-ref='txAdvice'/>
<aop:advisor pointcut='execution(* org.springside.core.dao.*Dao.*(..))' advice-ref='txAdvice'/>
</aop:config>
<tx:advice id='txAdvice'>
<tx:attributes>
<tx:method name='get*' read-only='true'/>
<tx:method name='find*' read-only='true'/>
<tx:method name='*'/>
</tx:attributes>
</tx:advice>
注意:pointcut 中包名需替換為專案實際包(如 com.xkland.manager.*Manager)。
public class WelcomeAction extends Action {
private UserManager userManager; private RoleManager roleManager; private GroupManager groupManager;
// setters 注入
public ActionForward execute(...) {
Role role = new Role(); role.setName('第一個角色'); role.setPrivilegesFlag('1,2,3,4,'); roleManager.save(role);
User user = new User(); user.setName('abcdefg'); user.setPassword(md5); user.setMonicker('abcdefg'); user.setRole(roleManager.get(1)); userManager.save(user);
Group group = new Group(); group.setName('第一個用戶組'); group.setCreator(user); groupManager.save(group);
// 建立雙向關聯
user = userManager.get(1); group = groupManager.get(1);
user.getGroups().add(group); group.getUsers().add(user);
userManager.save(user); groupManager.save(group);
return new ActionForward('/welcome.jsp');
}
}
開啟 hibernate.show_sql=true 可觀察生成 SQL,驗證映射正確性。
掌握 Hibernate Annotation 映射細節(主控方選擇、雙向關聯、insertable=false、Temporal 類型、軟刪除),結合 SpringSide 基礎 DAO,可快速構建健壯持久層。實戰中註重細節,避免常見映射陷阱。