京山游侠

专注技术,拒绝扯淡
posts - 50, comments - 868, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

在这里,将创建一个简化的用户管理模块,演示怎样利用SpringSide提供的数据持久层的功能,包括怎样通过Hibernate的Annotation来配置多对一映射和多对多映射。

大家都知道,现在最流行用户管理模型的是RBAC,也就是基于角色的访问控制模型,在这种模型中,可以划分多个层次,如用户-角色-资源、用户-角色-权限-资源、用户-角色-角色组-权限-资源、用户-角色-角色组-权限-操作-资源等等,因此,想要创建一个完善而复杂的用户管理模块,是相当具有难度的。在Web2.0时代,有一个很重要的开发思想,那就是先让程序跑起来,以后再逐步添加复杂的功能。因此,在这里只创建一个简化的用户管理模块。

所谓简化,它具有如下几个特点:

1.在认证方式中,选择基于用户名和密码的认证,用户需要提供用户名、密码和昵称,用户名和昵称都要求不能重复,用户名不能包含中文,且不能够被修改,昵称可以为中文,也可以被修改。密码使用MD5加密。

2.不包含用户的真实信息,如姓名、年龄、性别、职业、地址、邮编等等,因为如果包含这些字段,那么还需要包含更多的额外字段来让用户决定是否公开这些信息,因此,去掉这些东西,可以简化开发过程,让网站能够尽快的跑起来。

3.联系方式只需要用户提供它的电子邮箱和QQ号码。

4.如果用户密码丢失,可以通过密码提示问题找回,随机产生的新密码会发到用户的电子邮箱。

5.省略用户的个性化设置,如个性化签名、自定义头像等。

6.要能够记录用户的注册时间和最后登录时间。

7.要具有完善的积分和排名机制。

8.用户删除的时候不做物理删除,只标记为该用户不可用。

8.具有简化的角色和权限管理机制,这里的简化主要有以下几点:每个用户只能属于一个角色,即多对一关系,而不是传统的多对多关系;角色不需要分组;没有专门的资源抽象层;在角色表中只使用一个字段来表示该角色具有的权限,权限以数字表示,以逗号分开,如“1,2”,“1,3,15”等等。

9.用户可以创建群和加入群,为了简化,群的创始人即为管理员,并不可改变,用户加入群需要管理员批准,一个用户可以加如多个群,即多对多关系。

从上面的描述可以看出,一个简化的用户管理系统最少需要三个表,即users,roles和groups表,其中users和roles之间为多对一映射,users和groups之间为多对多映射,为了实现多对多映射,并且用户加入群的时候需要管理员批准,需要一个中间表users_groups。下面是在MySQL中创建数据表的语句。

创建用户表:

create   table  users(
id 
int   not   null  auto_increment  primary   key ,
name 
varchar ( 20 not   null ,
password 
char ( 32 not   null ,
monicker 
varchar ( 30 not   null ,
question 
varchar ( 30 not   null ,
answer 
varchar ( 30 not   null ,
email 
varchar ( 40 not   null ,
qq 
varchar ( 12 not   null ,
roleid 
int   not   null ,
score 
int   not   null   default   ' 0 ' ,
regtime 
timestamp   not   null   default   CURRENT_TIMESTAMP ,
logintime 
timestamp   not   null   default   ' 2007-01-01 00:00:00 ' ,
isdeleted 
varchar ( 2 not   null   default   ' 0 ' ,
index (username),
index (monicker));


为了加快查找用户的速度,在用户名和昵称列上创建了索引。

创建角色表:

create   table  roles(
id 
int   not   null  auto_increment  primary   key ,
name 
varchar ( 20 not   null ,
privilegesFlag 
varchar ( 255 ),
index (rolename)
);


创建群组表:

create   table  groups(
id 
int   not   null  auto_increment  primary   key ,
name 
varchar ( 40 not   null ,
creatorid 
int   not   null ,
createtime 
timestamp   not   null   default   CURRENT_TIMESTAMP ,
isdeleted 
varchar ( 2 not   null   default   ' 0 ' ,
index (groupname));


creatorid代表组的创始人,同时也是管理员,这里同样设置群组不做物理删除。

创建用户群组多对多映射辅助表:

create   table  users_groups(
id 
int   not   null  auto_increment  primary   key ,
userid 
int   not   null ,
groupid 
int   not   null ,
jointime 
timestamp ,
status 
tinyint ,
index (userid),
index (groupid)
);


其中status列代表用户是否通过了管理员的批准,为了加快查找速度,在userid和groupid列上建立索引。

设计完数据库,就该设计领域对象了,领域对象的设计方法为先设计简单的POJO,然后再在POJO上添加Hibernate Annotation来配置映射关系。在进行Annotation配置的时候,可以从以下几个方面进行思考。

1、使用什么样的数据类型映射数据库中的列类型?
2、对象之间是一对一、一对多还是多对多关系?
3、关联的对象之间哪一个作为主控方?
4、对象之间的关联是单向的还是双向的?

首先来看看users和roles之间的关系,考虑到加载一个用户数据的时候,往往同时需要知道他属于哪个角色,而加载一个角色的时候,就没有必要知道它管理哪些用户了,因此,它们是简单的单向关系,是多对一映射。当出现多对一映射的时候,永远都应该选择多的这一方作为主控方,道理很简单,打个比方,让一个国家元首记住全国人民的名字基本是不可能的,而让全国人民记住国家元首的名字就很简单了。因此,这里User作为主控方,Role作为被控方。

再来看看数据类型的映射,对于简单的int、varchar这样的就不用多说了。而日期时间类型的映射是一个重点,可以看到,前面的数据库创建语句中,所有需要时间的地方都使用了timestamp列类型,使用timestamp列类型的唯一目的就是为了能够使用default CURRENT_TIMESTAMP语句,使用date和datetime类型就不行,在MySQL中,timestamp只能表示从'1970-01-01 00:00:00'到2037年的范围。

MySQL中的timestamp和java.sql.Timestamp表现不一致,在MySQL中,timestamp和datetime类型精度是一样的,都只能储存到整数秒,而timestamp比datetime能表示的时间范围要小得多,在Java中,java.util.Date和MySQL的timestamp的精度是一致的,只能储存到整数秒,而java.sql.Timestamp还保存毫微秒,因此建议使用java.util.Date来映射timestamp列,使用java.sql.Timestamp只是浪费。

MySQL和Java在时间上面还有一个冲突,那就是MySQL支持全零的时间,如'0000-00-00 00:00:00',而Java不支持,因此如果在定义users表的logintime列时使用logintime timestamp not null default '0000-00-00 00:00:00',那么在使用Hibernate来获取User对象的时候就会出错,所以在创建数据库的时候要选择一个合法的默认时间,如'2007-01-01 00:00:00'。

下面请看User.java的代码:

package  com.xkland.domain;

import  java.io.Serializable;
import  java.util.Date;
import  org.springside.core.dao.extend.Undeletable;
import  org.hibernate.annotations.Cache;
import  org.hibernate.annotations.CacheConcurrencyStrategy;
import  javax.persistence. * ;

@Entity
@Table(name
= " users " )
@Undeletable(status
= " isDeleted " )
public   class  User  implements  Serializable  {
 
private  Integer id;
 
private  String name;
 
private  String password;
 
private  String monicker;
 
private  String question;
 
private  String answer;
 
private  String email;
 
private  String qq;
 
private  Role role;
 
private  Integer score;
 
private  Date regTime;
 
private  Date loginTime;
 
private  Byte isDeleted;
 
 @Id
 @GeneratedValue(strategy 
=  GenerationType.AUTO)
 
public  Integer getId()  {
  
return  id;
 }

 
public   void  setId(Integer id)  {
  
this .id  =  id;
 }

 
 
public  String getName()  {
  
return  name;
 }

 
public   void  setName(String name)  {
  
this .name  =  name;
 }

 
 
public  String getPassword()  {
  
return  password;
 }

 
public   void  setPassword(String password)  {
  
this .password  =  password;
 }

 
 
public  String getMonicker()  {
  
return  monicker;
 }

 
public   void  setMonicker(String monicker)  {
  
this .monicker  =  monicker;
 }

 
 
public  String getQuestion()  {
  
return  question;
 }

 
public   void  setQuestion(String question)  {
  
this .question  =  question;
 }

 
 
public  String getAnswer()  {
  
return  answer;
 }

 
public   void  setAnswer(String answer)  {
  
this .answer  =  answer;
 }

 
 
public  String getEmail()  {
  
return  email;
 }

 
public   void  setEmail(String email)  {
  
this .email  =  email;
 }

 
 
public  String getQq()  {
  
return  qq;
 }

 
public   void  setQq(String qq)  {
  
this .qq  =  qq;
 }

 
 @ManyToOne
 @JoinColumn(name
= " roleid " )
 
public  Role getRole()  {
  
return  role;
 }

 
public   void  setRole(Role role)  {
  
this .role  =  role;
 }

 
 @Column(name
= " score " ,insertable = false )
 
public  Integer getScore()  {
  
return  score;
 }

 
public   void  setScore(Integer score)  {
  
this .score  =  score;
 }

 
 @Column(name 
=   " regtime " ,insertable = false )
 @Temporal(TemporalType.TIMESTAMP)
 
public  Date getRegTime()  {
  
return  regTime;
 }

 
public   void  setRegTime(Date regTime)  {
  
this .regTime  =  regTime;
 }

 
 @Column(name 
=   " logintime " ,insertable = false )
 @Temporal(TemporalType.TIMESTAMP)
 
public  Date getLoginTime()  {
  
return  loginTime;
 }

 
public   void  setLoginTime(Date loginTime)  {
  
this .loginTime  =  loginTime;
 }

 
 @Column(name 
=   " isdeleted " ,insertable = false )
 
public  Byte getIsDeleted()  {
  
return  isDeleted;
 }

 
public   void  setIsDeleted(Byte isDeleted)  {
  
this .isDeleted  =  isDeleted;
 }
 
}

这里只对几个特殊的Annotation做一下注释:
1、因为创建数据表的时候使用的是users,而实体类为User,单复数不同引发名称不一致,因此需要@Table(name="users");
2、因为该表中的数据不做物理删除,所以加上@Undeletable(status="isDeleted"),结合SpringSide提供的HibernateEntityExtendDao类,可以在调用remove方法的时候将isdeleted列设置为"-1";
3、创建数据表的时候,所有的列名都是用的小写字母,因此有的列映射需要明确指定,如@Column(name = "logintime",insertable=false);
4、对于在创建数据表的时候定义了默认值的列,如regtime、regtime、logintime、isdeleted,在向数据库中添加数据的时候,可以不在insert语句中指定这些列,而让它们使用默认值,因此,需要告诉Hibernate在生成insert语句的时候不要包含这些列,可以使用insertable=false语句,如@Column(name = "regtime",insertable=false);
5、指定时间精度,使用@Temporal(TemporalType.TIMESTAMP);
6、指定users表通过roleid和roles表进行多对一映射,使用@ManyToOne和@JoinColumn(name="roleid")

Role.java则比较简单,如下:

package  com.xkland.domain;

import  java.io.Serializable;

import  javax.persistence.Entity;
import  javax.persistence.GeneratedValue;
import  javax.persistence.GenerationType;
import  javax.persistence.Id;
import  javax.persistence.Table;

@Entity
@Table(name
= " roles " )
public   class  Role  implements  Serializable  {
 
private  Integer id;
 
private  String name;
 
private  String privilegesFlag;
 
 @Id
 @GeneratedValue(strategy 
=  GenerationType.AUTO)
 
public  Integer getId()  {
  
return  id;
 }

 
public   void  setId(Integer id)  {
  
this .id  =  id;
 }

 
 
public  String getName()  {
  
return  name;
 }

 
public   void  setName(String name)  {
  
this .name  =  name;
 }

 
 
public  String getPrivilegesFlag()  {
  
return  privilegesFlag;
 }

 
public   void  setPrivilegesFlag(String privilegesFlag)  {
  
this .privilegesFlag  =  privilegesFlag;
 }

}


下一步再来看看users和groups之间的映射关系,不难想象,当载入一个用户的资料时,往往需要知道他加入了哪些群,而载入一个群的资料时,往往需要知道它有哪些用户,因此,他们之间是一个双向的关系,同时,载入一个群的资料时,还需要知道它的管理员是谁,因此又同时存在一个单向的多对一关系。在多对多关系中,设定User为主控方,所以需要在User.java中添加如下代码?

private  List < Group >  groups;
@ManyToMany(targetEntity
= User. class ,
 cascade
= {CascadeType.PERSIST, CascadeType.MERGE} )
@JoinTable(name
= " users_groups " ,
 joinColumns
= {@JoinColumn(name = " userid " )} ,
 inverseJoinColumns
= {@JoinColumn(name = " groupid " )} )
public  List < Group >  getGroups()  {
 
return  groups;
}

public   void  setGroups(List < Group >  groups)  {
 
this .groups  =  groups;
}


而整个Group.java的代码如下:

package  com.xkland.domain;

import  java.io.Serializable;
import  java.util.Date;
import  java.util.List;
import  org.springside.core.dao.extend.Undeletable;
import  org.hibernate.annotations.Cache;
import  org.hibernate.annotations.CacheConcurrencyStrategy;
import  javax.persistence. * ;

@Entity
@Table(name
= " groups " )
@Undeletable(status
= " isDeleted " )
public   class  Group  implements  Serializable  {
    
private  Integer id;
    
private  String name;
    
private  User creator;
    
private  Date createTime;
    
private  String isDeleted;
    
    
private  List < User >  users;

    @Id
    @GeneratedValue(strategy 
=  GenerationType.AUTO)
    
public  Integer getId()  {
        
return  id;
    }

    
public   void  setId(Integer id)  {
        
this .id  =  id;
    }

    
    
public  String getName()  {
        
return  name;
    }

    
public   void  setName(String name)  {
        
this .name  =  name;
    }

    
    @ManyToOne(cascade
= {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinColumn(name
= " creatorid " )
    
public  User getCreator()  {
        
return  creator;
    }

    
public   void  setCreator(User creator)  {
        
this .creator  =  creator;
    }

    
    @Column(name
= " createtime " ,insertable = false )
    @Temporal(TemporalType.TIMESTAMP)
    
public  Date getCreateTime()  {
        
return  createTime;
    }

    
public   void  setCreateTime(Date createTime)  {
        
this .createTime  =  createTime;
    }


    @Column(name
= " isdeleted " ,insertable = false )
    
public  String getIsDeleted()  {
        
return  isDeleted;
    }

    
public   void  setIsDeleted(String isDeleted)  {
        
this .isDeleted  =  isDeleted;
    }


    @ManyToMany(cascade
= {CascadeType.PERSIST, CascadeType.MERGE} ,
            mappedBy
= " groups " ,
            targetEntity
= User. class )
    
public  List < User >  getUsers()  {
        
return  users;
    }

    
public   void  setUsers(List < User >  users)  {
        
this .users  =  users;
    }


}

 

好了,该开始测试了,看看经过前面设计和配置的代码能否正常工作。首先,先创建三个Manager,这三个Manager都继承自org.springside.core.dao.extend.HibernateEntityExtendDao,至于HibernateEntityExtendDao的功能,请参考SpringSide的文档。代码如下:
UserManager.java:

package  com.xkland.manager;

import  org.springside.core.dao.extend.HibernateEntityExtendDao;
import  com.xkland.domain.User;

public   class  UserManager  extends  HibernateEntityExtendDao < User >   {
 
}



RoleManager.java:

package  com.xkland.manager;

import  org.springside.core.dao.extend.HibernateEntityExtendDao;
import  com.xkland.domain.Role;

public   class  RoleManager  extends  HibernateEntityExtendDao < Role >   {
 
}


GroupManager.java:

package  com.xkland.manager;

import  org.springside.core.dao.extend.HibernateEntityExtendDao;
import  com.xkland.domain.Group;

public   class  GroupManager  extends  HibernateEntityExtendDao < Group >   {

}


下一步,将User.class、Role.class、Group.class等领域对象添加到src\main\resources\config\hibernate.cfg.xml中,如下:

<! DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>

< hibernate-configuration >
    
< session-factory >
        
< mapping  class ="com.xkland.domain.Role" />
        
< mapping  class ="com.xkland.domain.User" />
        
< mapping  class ="com.xkland.domain.Group" />
    
</ session-factory >
</ hibernate-configuration >


再下一步,将上面的三个Manager类交给Spring管起来,配置src\main\resources\spring\serviceContext.xml,如下:

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd" >
< beans  default-lazy-init ="true"  default-autowire ="byName" >
    
< bean  id ="roleManager"  class ="com.xkland.manager.RoleManager" />
    
< bean  id ="userManager"  class ="com.xkland.manager.UserManager" />
    
< bean  id ="groupManager"  class ="com.xkland.manager.GroupManager" />
</ beans >


最后一步,编写一个Action类,用Spring将上面的三个Manager注入到Action中,测试能否顺利的操作数据库。Action类的代码如下:

package  com.xkland.action;

import  org.apache.struts.action.Action;
import  org.apache.struts.action.ActionForward;
import  org.apache.struts.action.ActionForm;
import  org.apache.struts.action.ActionMapping;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;
import  com.xkland.manager. * ;
import  com.xkland.domain. * ;

public   class  WelcomeAction  extends  Action  {
 
private  RoleManager roleManager;
 
private  UserManager userManager;
 
private  GroupManager groupManager;
 
 
// 以下代码的作用是注入三个Manager
  public   void  setUserManager(UserManager userManager)  {
  
this .userManager  =  userManager;
 }


 
public   void  setRoleManager(RoleManager roleManager)  {
  
this .roleManager  =  roleManager;
 }

 
 
public   void  setGroupManager(GroupManager groupManager) {
  
this .groupManager  =  groupManager;
 }

 
 
public  ActionForward execute(
   ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response
   )
{
  
  
// 以下代码测试能否添加role
  Role role  =   new  Role();
  role.setName(
" 第一个角色 " );
  role.setPrivilegesFlag(
" 1,2,3,4, " );
  roleManager.save(role);
  
  
// 以下代码测试能否添加user
  User user  =   new  User();
  user.setAnswer(
" aa " );
  user.setEmail(
" aa " );
  user.setQq(
" aa " );
  user.setName(
" abcdefg " );
  user.setPassword(
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " );
  user.setQuestion(
" aa " );
  user.setMonicker(
" abcdefg " );
  user.setRole(roleManager.get(
1 ));
  userManager.save(user);
  
  
// 以下代码测试能否添加group
  Group group  =   new  Group();
  group.setName(
" 第一个用户组 " );
  group.setCreator(user);
  groupManager.save(group);
  
  
// 以下代码测试将user和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 " );
 }

}



怎样配置Action这里就不用多嘴了,请参考SpringSide的文档。这里还要说一句,一定要记得修改src\main\resources\spring\applicationContext.xml中的事务配置中的package,否则运行会出错,配置文件片断如下:

<!--  以AspectJ方式 定义 AOP  -->
    
< aop:config  proxy-target-class ="true" >
        
<!--  注意,请把第2个*号换为项目package  -->
        
< aop:advisor  pointcut ="execution(* *..manager.*Manager.*(..))"  advice-ref ="txAdvice" />
        
< aop:advisor  pointcut ="execution(* org.springside.core.dao.*Dao.*(..))"  advice-ref ="txAdvice" />
    
</ aop:config >

    
<!--  基本事务定义,使用transactionManager作事务管理,默认get*方法的事务为readonly,其余方法按默认设置.
             默认的设置请参考Spring文档事务一章. 
-->
    
< 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 >


 如果有兴趣,还可以把hibernate.show_sql设置为true,以便观察Hibernate生成的SQL语句,如下图:
29.JPG


评论

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-01-05 17:15 by cc[匿名]
so fast!
加油,跟着你的springside系列文章学到了很多东西!

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-01-05 18:59 by suwu
非常好,明白多了。。。。。

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-01-08 00:02 by willlim
你真棒,希望你能继续写这么好的文章,会跟着一起学习的

# 再谈一下数据库的备份策略  回复  更多评论   

2007-01-09 17:48 by 海边沫沫
  开发一个Web系统,在决定好使用什么开发技术和使用什么应用服务器之后,接下来的事情就应该考虑数据怎样储存的问题了。使用数据库自然是不二的选择,在这里,我选择MySQL 5.0以上的版本。数据库中仅存储文本信息和上传的图片保存为什么文件名和属于哪个用户,而图片文件则一律保存在硬盘上。

  首先,我把MySQL的数据目录改到一个单独的磁盘分区,这样,当我重装应用软件的时候就不会影响到数据。先在E:/盘创建一个目录MySQL_Data,然后打开MySQL安装目录下的my.ini文件,修改修改[mysqld]节的配置:
  datadir="E:/MySQL_Data/"

  下一步就是做一个数据备份的策略,既然我已经决定要把所有数据永久保存,那么数据备份就是非常重要的一件事情了,只有经常备份,才能防止意外造成数据丢失。我做的备份策略是这样的:
  1.数据库引擎选择InnoDB,尽管它比MyISAM引擎要慢3-5倍,但是它是事务安全的,而且在服务器异常崩溃后,再次重启服务器可以自动修复受损的数据表,这样修改配置文件:
  default-storage-engine=INNODB
  2.创建专门的文件夹来储存InnoDB的表空间文件和日志文件,在数据目录下创建一个ibdata文件夹,并如下修改配置文件:
  innodb_data_home_dir = ./ibdata
  innodb_log_group_home_dir = ./ibdata
  innodb_data_file_path=ibdata1:50M:autoextend:max:1G

  这里我们先创建一个表空间文件,初始大小为50M,并可以自动增长,最大文件大小限制为1G,达到最大值之后,我们可以再添加一个表空间文件。
  3.固定时间备份,比如客流量不大的时候,可以每周备份一次,客流量大的时候可以每天备份一次。第一次备份时,使用mysqldump做一个完全备份,以后的备份,可以进行增量备份。增量备份的时候,需要启用二进制日志,我们这样修改配置:
  log-bin=./bin_log/binlog
  也就是在数据目录下专门创建一个目录bin_log来保存二进制日志文件。另外,我们希望只记录我们工作的这个数据库的二进制日志,而忽略其它的数据库。配置文件这样修改:
  binlog-do-db=dbname

# re: SpringSide开发实战(四):打通数据持久层的任督二脉[未登录]  回复  更多评论   

2007-01-16 10:23 by limq
顶一个,不错

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-01-18 00:13 by billbai
辛苦了哈!很好的,我也正想试下这个,有没有自动生成实体文件的,不用手工写的

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-01-22 12:56 by 刘金龙
这个东西没有什么技术含量,只不过hibernate充分利用了Annotation特性而已,建议好好研究一下标签,呵呵

# 8771100  回复  更多评论   

2007-03-15 17:54 by 000
0000

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-05-20 15:52 by feifei
我啥都不说了```````、顶````

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-07-30 16:11 by 小白之家
这个有点难

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-07-30 16:17 by 小白之家
能给源码打个包,look一下吗?

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-10-17 23:46 by liuxiaoxia_555@163.com
这样做的话,在删除group的时候会出错啊!能说说怎么能删除group的同时把user保留!而只是把usergroup表中的数据删掉?

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-10-18 11:48 by 海边沫沫
楼上的说得有道理,我在写测试代码的时候只考虑到了添加,而没有考虑到删除。至于会不会出错,我认为不会,多对多关系删除一方的时候不会删除另外一方吧。

就算确实会出错,我们也可以在Hibernate中使用hql语句或SQL语句来直接操纵数据库。

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2007-12-15 17:27 by Relax Lin
太强拉,,,,,,,,,顶

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2008-01-18 17:48 by nicholas85211
很透彻

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2008-06-28 15:29 by wzz
测试可以用 user.setRole(roleManager.get( 1 ));。但是在Form页面中怎么办呢?form中传过来的是String类型的数据啊,不是Role型的数据。会报错的如:
System Runtime Error:
Unexpected reflection exception - java.lang.IllegalArgumentException: Cannot invoke com.fh.tms.model.User.setRole - argument type mismatch
这个问题可以解决吗?

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2008-08-13 08:09 by 笑笑笑笑笑笑笑
re: SpringSide开发实战(四):

# re: SpringSide开发实战(四):打通数据持久层的任督二脉  回复  更多评论   

2008-12-07 19:55 by 虎啸龙吟
纠正一下建表的几个小错误,正确的如下:
create table users(
id int not null auto_increment primary key ,
username varchar ( 20 ) not null ,
password char ( 32 ) not null ,
monicker varchar ( 30 ) not null ,
question varchar ( 30 ) not null ,
answer varchar ( 30 ) not null ,
email varchar ( 40 ) not null ,
qq varchar ( 12 ) not null ,
roleid int not null ,
score int not null default ' 0 ' ,
regtime timestamp not null default CURRENT_TIMESTAMP ,
logintime timestamp not null default ' 2007-01-01 00:00:00 ' ,
isdeleted varchar ( 2 ) not null default ' 0' ,
index (username),
index (monicker)
);

create table roles(
id int not null auto_increment primary key ,
rolename varchar ( 20 ) not null ,
privilegesFlag varchar ( 255 ),
index (rolename)
);

create table groups(
id int not null auto_increment primary key ,
groupname varchar ( 40 ) not null ,
creatorid int not null ,
createtime timestamp not null default CURRENT_TIMESTAMP ,
isdeleted varchar ( 2 ) not null default ' 0' ,
index (groupname)
);

create table users_groups(
id int not null auto_increment primary key ,
userid int not null ,
groupid int not null ,
jointime timestamp ,
status tinyint ,
index (userid),
index (groupid)
);

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问