2010年7月30日星期五

充血模型设想实现

充血模型设想实现: " 早两年,贫血模型和充血模型在javaeye讨论的很热闹,但在具体实现时争论的比较多,关键还是由于Java不比动态语言那么容易去实现,如果能够在领域模型中动态添加相关访问数据库的方法,会是什么情况。下面借鉴rails去实现一个充血领域模型。

最近对操作字节码比较感兴趣,想到在编译领域模型时,动态添加相关的字节码,达到丰富领域模型,同时需要hibernate 的支持,获取所有@Entity的领域模型,添加HibernateTemplate Field,借助aspectj,实例化领域模型时,注入hibernateTemplate。(Spring Roo就是这么实现的...),考虑也把jdbcTemplate添加进去。。。


顺带为所有field生成getter和setter。
// ASM 添加的方法:
@Transient
private HibernateTemplate hibernateTemplate;
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}


每一个entity添加一些persistence方法,可以省去DAO层。业务层管理事务,安全等方面逻辑, 添加如下的代码的字节码,具体参考附件中代码。在实际中,增加一个ant命令。批量添加字节码。


public void create() throws DataAccessException {
hibernateTemplate.save(this);
}

public void createOrUpdate() throws DataAccessException {
hibernateTemplate.saveOrUpdate(this);
}

public void delete() throws DataAccessException {
hibernateTemplate.delete(this);
}

public Message find() throws DataAccessException {
return hibernateTemplate.get(this.getClass(), id);
}

public void update() throws DataAccessException {
hibernateTemplate.update(this);
}

public List<Message> findByProperty(String propertyName, Object value) throws DataAccessException {
Assert.hasText(propertyName);
Assert.notNull(value);

StringBuilder buf = new StringBuilder();
buf.append("FROM ").append(this.getClass().getSimpleName()).append(" WHERE ").append(propertyName).append(" = :condition");
List<Message> entities = this.getHibernateTemplate().findByNamedParam(buf.toString(), "condition", value);
return entities;
}

public List<Message> findAll() throws DataAccessException {
return (List<Message>) hibernateTemplate.loadAll(this.getClass());
}




测试的实例如下:

原始Message entity代码只定义Field


@Entity
@Table(name='messages')
public class Message1 {
@Id
@GeneratedValue
@Column(name='message_id')
private Long id;
@Column(name='message_text')
private String text;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name='next_message_id')
private Message1 nextMessage;
}


为方便测试手动注入hibernateTemplate到message对象中。


final HibernateTemplate hibernateTemplate = new HibernateTemplate();
HibernateTransactionManager transactionManager = new HibernateTransactionManager(HibernateSessionFactory.getSessionFactory());
hibernateTemplate.setSessionFactory(HibernateSessionFactory.getSessionFactory());
hibernateTemplate.afterPropertiesSet();
transactionManager.afterPropertiesSet();

TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
Message message = new Message();
message.setHibernateTemplate(hibernateTemplate);

message.setText("Hello World");
message.create();

List<Message> list = message.findAll();
System.out.println(list.size() + "message(s) found");
}
});

HibernateSessionFactory.getSessionFactory().close();




完成了试验测试以后,但感觉实际开发有点不方便。修改了entity代码,就需要重新修改字节码,虽然用ant可以带来一些方便, 如果不在entity添加业务方法,修改entity机会不多,可以接受的,如果想在entity添加业务方法,丰富充血模型,就有点麻烦。

不过还好,从lombok那,学到一种解决思路,在eclipse编译java代码时,同时添加字节码,看了lombok的代码,有的复杂... 后期有时间再去实现...







    本文附件下载:

  • Roo.rar (40.7 KB)







作者: melin


声明: 本文系JavaEye网站发布的原创文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!




已有 0 人发表回复,猛击->>这里<<-参与讨论





JavaEye推荐






"

没有评论:

发表评论