首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SpringSide 實戰(四):Hibernate Annotation 打通數據持久層——多對一與多對多映射實戰

     編輯:Java 相關知識

簡化用戶管理模型設計

基於 RBAC 思想簡化:

  • 認證:用戶名/密碼/暱稱,用戶名/暱稱唯一,密碼 MD5
  • 無真實信息(姓名、年齡等)
  • 聯系:Email、QQ
  • 密碼找回:問題/答案,新密碼發郵箱
  • 記錄註冊/最後登錄時間
  • 積分排名機制
  • 軟刪除:isDeleted 標記
  • 角色:用戶單一角色(多對一),權限用逗號分隔字符串存儲
  • 群組:用戶可創建/加入多群(多對多),創始人為管理員不可變,加入需審批

三張核心表:users、roles、groups,加中間表 users_groups(含 status 審批狀態)。

領域對象與 Hibernate Annotation 映射

User.java

@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 為主控方

Role.java

@Entity @Table(name='roles')
public class Role implements Serializable {
  @Id @GeneratedValue Integer id;
  String name, privilegesFlag; // getters/setters
}

Group.java

@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 層與 Spring 配置

三個 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)。

Action 測試數據操作

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,可快速構建健壯持久層。實戰中註重細節,避免常見映射陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved