流程说明:实现一组功能的步骤
l 1,充分了解需求,包括所有的细节,需要知道要做一个什么样的功能
l 2,设计实体/表
• 正向工程:设计实体、映射文件à 建表
• 反向工程:设计表 à 映射文件、实体
l 3,分析功能
• 分析到每个请求的粒度。
• 得到的结果是我们需要处理多少种请求,其中每种请求对应一个Action方法。
l 4,实现功能:
• 1,创建Action,并定义出其中的方法。
• 2,实现Action方法,并创建出所用到的新的Service方法。
• 3,实现Service方法,并创建出所用到的新的Dao方法。
• 4,实现Dao方法。
• 5,创建并完成JSP页面。
l 5,测试、运行
l 完成
流程总结:设计实体
l 1,有几个实体?
• 一般是一组增删改查对应一个实体。
l 2,实体之间有什么关系?
• 一般是页面引用了其他的实体时,就表示与这个实体有关联关系。
l 3,每个实体中都有什么属性?
• 1,主键。
• 2,关联关系属性。在类图中,关联关系是一条线,有两端,每一端对应一个表达此关联关系的属性。有几个端指向本类,本类中就有几个关联关系属性。
• 3,一般属性。分析所有有关的页面,找出表单中要填写的或是在显示页面中要显示的信息等。
• 4,特殊属性:为解决某问题而设计的属性。比如要显示年龄,但不会设计一个int age字段,而是一个Date birthday字段,年龄是在显示时实时计算出来的。
l 完成
OA实体类图1
流程总结:Hibernate实体映射
l 1,写注释
• 格式为:?属性,表达的是本对象与?的?关系。
• 例:“department属性,本对象与Department的多对一”
l 2,拷模板
多对一 | <many-to-one name=“” class=“” column=“”/> |
一对多 (Set) | <set name=""> <key column=""></key> <one-to-many class=""/> </set> |
多对多 (Set) | <set name="" table=""> <key column=""></key> <many-to-many class="" column=""/> </set> |
l 3,填空:
• name属性:属性名(注释中的第1问号)
• class属性:关联的实体类型(注释中的第2个问号)
• column属性:
• <many-to-onecolumn="..">:一般可以写成属性名加Id后缀,如属性为department,则column值写成departmentId。
• 一对多中的<key column="..">:从关联的对方(对方是多对一)映射中把column值拷贝过来。
• 多对多中的<key column=“..”>:一般可以写成本对象的名加Id后缀,如本对象名为User,则写为userId
• 多对多中的<many-to-many column=“..”>:一般可以写为关联对象的名称加Id后缀。
l 完成
分析增删改查功能
• 添加、修改、删除成功后 要重定向到列表功能,这样在刷新页面时才不会出现“又做一次增、删、改”的操作。
• 列表与删除功能都是只有一个请求
• 添加与修改功能都是有两个请求
l 增删改查共4个功能,6个请求,需要在Action中有6个对应的处理方法。
作用 | 方法名 | 返回值 | 对应的JSP页面 |
列表 | list() | list | list.jsp |
删除 | delete() | toList | |
添加页面 | addUI() | addUI | addUI.jsp |
添加 | add() | toList | |
修改页面 | editUI() | editUI | editUI.jsp |
修改 | edit() | toList |
重定向与转发的区别
请求数 浏览器地址栏
-------------------------------------------------------------------
转发 1 不变
重定向 2 变
增删改查所用的6个Action方法的模板
/** 列表 */
public String list()throws Exception{
return "list";
}
/** 删除 */
public String delete()throws Exception{
return "toList";
}
/** 添加页面 */
public String addUI()throws Exception{
return "saveUI";
}
/** 添加 */
public String add()throws Exception{
return "toList";
}
/** 修改页面 */
public String editUI()throws Exception{
return "saveUI";
}
/** 修改 */
public String edit()throws Exception{
return "toList";
}
设计BaseDao接口与BaseDaoImpl类
1、每个实体都应有一个对应的Dao,他封装了对这个实体的数据库操作。例
实体 Dao接口 实现类
========================================================
User -->UserDao -->UserDaoImpl
Role -->RoleDao -->RoleDaoImpl
Department -->DepartmentDao -->DepartmentDaoImpl
Article -->ArticleDao --> ArticleDaoImpl
...
2、类图设计UML图
说明:
1, 实体的Dao接口要继承BaseDao接口。
2, Dao的实现类要继承DaoImplBase类。
3, 也可以不继承指定的接口或类,这样就要自己写相应的方法。
4, T getById(Long id)与List<T>getByIdList(Long[] idList)不要合并为List getById(Long... ids),因为获取一个对象时也是返回List,不方便。
获取 BaseDao的类型参数T的Class
问题:
1, 有了DaoBase与DaoImplBase,还要用UserDao、RoleDao吗?
答:要用。因为UserDao或RoleDao中的方法可以分为有公有的方法与特有的方法两部分。公有的方法是通过继承BaseDao得到的,特有的方法要写在自己里面(BaseDao中是没有的)。
2, UserDaoImpl已经继承了BaseDaoImpl,就不实现UserDao可以吗?
答:不可以。否则UserDao userDao = newUserDaoImpl(); 就不成立。
使用反射获取类型参数的真实类型的代码如下:
public DaoBaseImpl () { Type type = this.getClass().getGenericSuperclass(); ParameterizedType pt = (ParameterizedType) type; this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; } |
说明:
1, 使用Session时,不要自己创建,也不要管理事务,直接调用getSession()即可。
2, 暂时不实现getSession()方法,在后面的事务管理中实现:
protected Session getSession(){
throw new UnsupportedOperationException();
}
BaseDaoImpl的实现
@Transactional
@SuppressWarnings("unchecked")
public class BaseDaoImpl<T>implements BaseDao<T>{
@Resource
private SessionFactorysessionFactory;
private Class<T> clazz;
public BaseDaoImpl(){
//通过反射得到T的真实类型
ParameterizedType parameterizedType=(ParameterizedType)this.getClass().getGenericSuperclass();
this.clazz=(Class<T>) parameterizedType.getActualTypeArguments()[0];
System.out.println(this.clazz.getName());
}
public void save(T entity){
getSession().save(entity);
}
public void delete(Long id){
Object obj=getSession().get(clazz, id);
getSession().delete(obj);
}
public void update(T entity){
getSession().update(entity);
}
public T getById(Long id){
return (T) getSession().get(clazz, id);
}
public List<T> getByIds(Long[] ids) {
if(ids==null|| ids.length==0){
return Collections.EMPTY_LIST;
}
return getSession().createQuery(//
"FROM "+clazz.getSimpleName()+" WHERE id IN (:ids)")//
.setParameterList("ids",ids).list();
}
public List<T> findAll(){
return getSession().createQuery(//
"FROM "+clazz.getSimpleName())//
.list();
}
/**
* 获取当前可用的session
* @return
*/
private Session getSession(){
return sessionFactory.getCurrentSession();
}
}