handong890 2011-01-28 11:27
浏览 574
已采纳

对充血模型的疑问

小弟我在坛子上看到关于贫血模型和充血模型的讨论后一直再想这对于我这种代码小工意味着啥?
是否可以更快更迅速更敏捷的完成代码完成开发。
一直做的项目都是SSH 然后分层 action,service,dao,entity;有时候我觉得dao层没什么必要啊,既然
hibernate是面向对象为何还要 dao.save(entity)   dao.update(entity) 这样操作?
感觉如果去掉dao层 直接entity.update(),entity.delete();  这样是否会更形象?
然后小弟开始尝试,首先搭了个struts2+spring3+Hibernate3.6的ssh工程用的是全注解搭法这样开发就不用写配置文件了还是相当的爽啊

首先我觉得应该有一个公共的类充当所有entity的父类


import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;

@Repository("MagicH")
public class MagicH extends HibernateTemplate {

@Resource(name = "sessionFactory")
public void setSuperSessionFactory(SessionFactory sessionFactory) {
    super.setSessionFactory(sessionFactory);
}

private Serializable id; // 标示
private Class clazz; // 实体
private Object entity; // 数据库实体
private PropertyDescriptor targetPds[];  //初始化后属性
private HashMap setMethodMap = new HashMap();   //set方法映射
private HashMap getMethodMap = new HashMap();  //get方法映射

/**
 * 模型初始化
 * 
 * @param clazz
 * @param id
 */
public boolean init(Class clazz, Serializable id) {
    this.id = id;
    this.clazz = clazz;
    PropertyDescriptor targetPds[] = BeanUtils.getPropertyDescriptors(clazz); 
      for (PropertyDescriptor pdObj : targetPds)
        {
           setMethodMap.put(pdObj.getName().toLowerCase(), pdObj.getWriteMethod());
           getMethodMap.put(pdObj.getName().toLowerCase(), pdObj.getReadMethod());
        }
      this.entity = get(clazz, id);
    return this.entity==null?false:true;  
}

/**
 * 获取对象实体
 * 
 * @return
 */
public Object getObj() {
    if (entity == null) {
        this.entity = get(clazz, id);
    }
    return entity;
}

/**
 * 删除对象实体
 */
public void delObj() {
    if (entity != null)
        delete(entity);
    else
        delete(get(clazz, id));
}

/**
 * 设置数据库实体属性
 * @param propertyName
 * @param propertyValue
 */
public void setProperty(String propertyName, Object propertyValue) {

      Method writeMethod = (Method) setMethodMap.get(propertyName.toLowerCase());
      try {
        writeMethod.invoke(entity, new Object[] {propertyValue});
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

/**
 * 获取属性的值
 * @param propertyName
 * @return
 */
public Object getPropertyValue(String propertyName)
{
    Method readMethod = (Method)getMethodMap.get(propertyName.toLowerCase());
    Object returnValue = null;
    try {
        returnValue = readMethod.invoke(entity,null);
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return returnValue;
}
/**
 * 更新对象
 */
public void updateObj()
{
    update(entity);
}


/**
 * 保存对象
 * @param obj
 * @return
 */
public Serializable addObj(Object obj)
{
    Serializable id =  save(obj);
    init(obj.getClass(),id);
    return  id;
}

}



建立一张用户表测试,对应实体如下

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.stereotype.Repository;

import com.usoft.core.dao.impl.MagicH;

/**

  • MagicUser entity. @author MyEclipse Persistence Tools
    */
    @Repository("MagicUser")
    @Entity
    @Table(name = "MAGIC_USER")
    public class MagicUser extends MagicH implements java.io.Serializable {

    // Fields

    private String userId;
    private String userNam;
    private String userSex;
    private String userPhone;

    // Constructors

    /** default constructor */
    public MagicUser() {
    }

    /** full constructor */
    public MagicUser(String userNam, String userSex, String userPhone) {
    this.userNam = userNam;
    this.userSex = userSex;
    this.userPhone = userPhone;
    }

    // Property accessors
    @GenericGenerator(name = "generator", strategy = "uuid.hex")
    @Id
    @GeneratedValue(generator = "generator")
    @Column(name = "USER_ID", unique = true, nullable = false, length = 32)
    public String getUserId() {
    return this.userId;
    }

    public void setUserId(String userId) {
    this.userId = userId;
    }

    @Column(name = "USER_NAM", length = 500)
    public String getUserNam() {
    return this.userNam;
    }

    public void setUserNam(String userNam) {
    this.userNam = userNam;
    }

    @Column(name = "USER_SEX", length = 1)
    public String getUserSex() {
    return this.userSex;
    }

    public void setUserSex(String userSex) {
    this.userSex = userSex;
    }

    @Column(name = "USER_PHONE", length = 11)
    public String getUserPhone() {
    return this.userPhone;
    }

    public void setUserPhone(String userPhone) {
    this.userPhone = userPhone;
    }

}


这是本人测试用的service


import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.usoft.magich.bs.ImagicServiceTest;
import com.usoft.magich.vo.MagicUser;

@Service("MagicService")
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public class MagicServiceTestImpl implements ImagicServiceTest {

@Resource
private MagicUser magicUser;

public void testMagicH() {
    //保存
    magicUser.setUserNam("用户123");
    magicUser.setUserPhone("12345");
    magicUser.setUserSex("1");
    magicUser.addObj(magicUser);

   //更新
    magicUser.setProperty("UserNam", "1234567");
    magicUser.updateObj();

    System.out.print(magicUser.getPropertyValue("UserNam"));

    boolean b1 = magicUser.init(magicUser.getClass(), "aaa");  //id 不存在初始化失败
    System.out.println(b1);

    boolean b2 = magicUser.init(magicUser.getClass(),"402881862da6ec3b012da6fb4f640004"); //id存在为 true
    System.out.println(b2);
    magicUser.delObj(); //删除 对象
}

}



只是中午吃饭时脑子那么想了一下,然后回来就尝试写了个单表的增删改查,我个人举得无论是单表还是多表最后数据库查出来的无非是个二叉表,而其中的一条记录应该对应一个java类 多条记录则是该java类的List集合,然后所有的数据库操作不再是dao.doSomething 而是entity.doSomething
我这样做了后写的代码就只有actiong,service,entity层了,不知道这样是否可行,谁能解释一下我的疑问。


问题补充
看了大家的回复深受启发,感觉自己这个想法似乎不可取就不再钻牛角尖了。
可能一直处于开发人员的角色,所以关系的核心问题无非就是 写最少的代码做最多的事
  • 写回答

21条回答 默认 最新

  • luzhou33 2011-01-28 11:27
    关注

    一个问题的作用域将决定一个问题的解决方案是否合适。其实这也是大多数人对于领域模型各种变种的误解。

    当一个简单类具备了field和method之后,大师们告诉你,这个类的实例叫做对象,基于这种方式写出来的程序叫OO。大师们还告诉你,只有field和它们对应的setter/getter方法的类,不怎么OO,因为这叫贫血。在类上加上method,赋予类逻辑执行能力,这叫领域模型,比较OO。

    恩,我们不妨考虑一个拥有3000w行代码的大系统,假设它需要1000个领域模型类。这相当于把一个最简单的问题放大了1000倍,那么我们等于把我们的逻辑重复1000遍。当然,这个系统的逻辑不再是增删改查那么简单,而是有复杂的业务流程。这个时候,你会发现,一个领域模型类可能将达到20K,甚至30K那么大。里面可能有超过40个method,对应30种不同的业务流程。

    某天,项目经理说,hey,小伙子,客户说这业务改了,它们要在所有涉及到数据库保存的地方加条日志,并通知另外一个系统。想象一下你的工作?在一个超过2000行的类里面,找到那些方法,一个个加过来。恩,这就是专家们说的,这很OO。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(20条)

报告相同问题?

悬赏问题

  • ¥100 求数学坐标画圆以及直线的算法
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站