`
cnoss
  • 浏览: 15564 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类

让你的 Ibatis2 也支持Annotation

阅读更多
在支持xml配置方式的基础上增加了对annotation的支持,用户可以根据自己的喜好来选择或者两种方式并存。详情请大家看:http://www.rest4g.org/viewthread.php?tid=12&extra=page%3D1

代码示例如下:
Account.java
package org.jrest4guice.persistence.ibatis;
public class Account {
  private int id;
  private String firstName;
  private String lastName;
  private String emailAddress;

  public int getId() {
    return id;
  }

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

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public String getEmailAddress() {
    return emailAddress;
  }

  public void setEmailAddress(String emailAddress) {
    this.emailAddress = emailAddress;
  }

}
AccountService.java
package org.jrest4guice.persistence.ibatis;
import java.sql.SQLException;
import java.util.List;
import org.jrest4guice.persistence.ibatis.annotations.Delete;
import org.jrest4guice.persistence.ibatis.annotations.IbatisDao;
import org.jrest4guice.persistence.ibatis.annotations.Insert;
import org.jrest4guice.persistence.ibatis.annotations.Result;
import org.jrest4guice.persistence.ibatis.annotations.ResultMap;
import org.jrest4guice.persistence.ibatis.annotations.Select;
import org.jrest4guice.persistence.ibatis.annotations.Update;
import org.jrest4guice.transaction.annotations.Transactional;
import org.jrest4guice.transaction.annotations.TransactionalType;

import com.google.inject.Inject;
import com.ibatis.sqlmap.client.SqlMapClient;

@IbatisDao
@SuppressWarnings("unchecked")
@Transactional
@ResultMap(id = "accountResultMap", result = {
		@Result(property = "id", column = "id"),
		@Result(property = "firstName", column = "firstName"),
		@Result(property = "lastName", column = "lastName"),
		@Result(property = "emailAddress", column = "emailAddress") }, resultClass = Account.class)
@Cachemodel(id = "account-cache", flushInterval = "24", flushOnExecute = {
		"insertAccount", "updateAccount", "deleteAccount" }, type = "LRU", 
		property = { @Property(name = "size", value = "100") })
public class AccountService {
	@Inject
	private SqlMapClient sqlMapper;

	@Select(id = "selectAllAccounts", sql = "select * from ACCOUNT", 
			resltMap = "accountResultMap", cacheModel = "account-cache")
	@Transactional(type = TransactionalType.READOLNY)
	public List<Account> findAll() throws SQLException {
		return sqlMapper.queryForList("selectAllAccounts");
	}

	@Select(sql = "select id ,firstName,lastName,emailAddress from "
			+ "ACCOUNT where id = #id#")
	@Transactional(type = TransactionalType.READOLNY)
	public Account getAccountById(int id) throws SQLException {
		return (Account) sqlMapper.queryForObject("getAccountById", id);
	}

	@Insert(id = "insertAccount", sql = "insert into ACCOUNT (id,firstName,"
			+ "lastName,emailAddress) values (#id#, #firstName#, #lastName#, "
			+ "#emailAddress#)")
	public void createAccount(Account account) throws SQLException {
		sqlMapper.insert("insertAccount", account);
	}

	@Update(sql = "update ACCOUNT set firstName = #firstName#,lastName = "
			+ "#lastName#,emailAddress = #emailAddress# where id = #id#")
	public void updateAccount(Account account) throws SQLException {
		sqlMapper.update("updateAccount", account);
	}

	@Delete(id = "deleteAccount", sql = "delete from ACCOUNT where id = #id#")
	public void deleteAccount(int id) throws SQLException {
		sqlMapper.delete("deleteAccount", id);
	}

	@Select(id = "queryAccounts", 
		sql = "select * from ACCOUNT "
			+ "<dynamic prepend=\"where\">"
			+ " <isNotNull prepend=\"and\" property=\"firstName\">"
			+ "    firstName = #firstName#" 
			+ " </isNotNull>"
			+ " <isNotNull prepend=\"and\" property=\"lastName\">"
			+ "    lastName = #lastName#" 
			+ " </isNotNull>"
			+ " <isNotNull prepend=\"and\" property=\"emailAddress\">"
			+ "    emailAddress = #emailAddress#" 
			+ " </isNotNull>"
			+ "</dynamic> " 
			+ "order by lastName", resltMap = "accountResultMap", 
			cacheModel = "account-cache")
	@Transactional(type = TransactionalType.READOLNY)
	/**
	 * 动态SQL查询
	 */
	public List<Account> queryAccounts(Account account) throws SQLException {
		return sqlMapper.queryForList("queryAccounts",account);
	}
}
AccountServiceTest.java
package org.jrest4guice.persistence.ibatis;

import java.sql.SQLException;
import java.util.List;
import junit.framework.Assert;
import org.jrest4guice.guice.GuiceContext;
import org.jrest4guice.guice.PersistenceGuiceContext;
import org.junit.BeforeClass;
import org.junit.Test;

public class AccountServiceTest {
	private static AccountService service;

	@BeforeClass
	public static void setUp() throws Exception {
		// 初始化JRest4Guice
		PersistenceGuiceContext.getInstance().useIbatis(
				"org.jrest4guice.persistence.ibatis").init();
		// 获取服务
		service = GuiceContext.getInstance().getBean(AccountService.class);
	}

	@Test
	public void doTest() {
		List<Account> accounts;
		try {
			Account account = new Account();
			account.setFirstName("张");
			account.setLastName("学友");
			account.setEmailAddress("jackey@rest4g.org");
			// 添加
			service.createAccount(account);

			account = new Account();
			account.setFirstName("刘");
			account.setLastName("学友");
			account.setEmailAddress("test@rest4g.org");
			// 添加
			service.createAccount(account);
			
			//查询(按lastName)
			Account queryCondition = new Account();
			queryCondition.setLastName("学友");
			accounts = service.queryAccounts(queryCondition);
			Assert.assertEquals(2, accounts.size());
			
			//查询(按firstName和lastName)
			queryCondition.setFirstName("张");
			accounts = service.queryAccounts(queryCondition);
			Assert.assertEquals(1, accounts.size());

			// 修改
			account = accounts.get(0);
			account.setFirstName("何");
			service.updateAccount(account);
			account = service.getAccountById(account.getId());
			Assert.assertNotNull(account);
			Assert.assertEquals("何", account.getFirstName());

			//查询所有
			accounts = service.findAll();
			Assert.assertEquals(2, accounts.size());

			// 删除
			for (Account ac : accounts){
				service.deleteAccount(ac.getId());
			}
			
			//断言删除的结果
			accounts = service.findAll();
			Assert.assertEquals(0, accounts.size());
		} catch (SQLException e) {
			Assert.fail(e.getLocalizedMessage());
		}
	}
}
分享到:
评论
55 楼 抛出异常的爱 2009-02-02  
Readonly 写道

偶的意见就是要分开多个配置文件,减少Line Of Code per File,减少维护成本,降低出错概率,分离关注点。

要用annotation,把它当作限制器.过滤不合格的数据源录入.使IDE事先捕获数据错误,减少测试代码,会有用的多.
54 楼 xzj127 2009-02-02  
太恶心了。
53 楼 piggy 2008-10-17  
不知道iBatis3什么时候出来.
52 楼 backbase 2008-10-17  
楼主非常强悍,永远支持你!
51 楼 cnoss 2008-10-17  
zhenjia 写道
比如你定义了一个@Insert(id='xx',sql='sql') 然后在这这方法上调xxService.insert('xx') 那还不如把sql直接写在xxService.insert('sql')呢 那个ID完全是多余的东西。

这个ID是解决ibatis sqlmapping中的sql引用的,在ibatis的用法中,可以指定另一个sql为当前查询的子查询,它们是通过这个id来引用的。

抽时间学习一下你的http://www.iteye.com/topic/232885
50 楼 zhenjia 2008-10-16  
看了一下, annotation用得比我还疯狂 呵呵 。但是我感觉你好象是把xml应该配置的东西以annotation形式写在JAVA里了。那么,请问一下?这有什么用,证明XML里的东西ANOTATION也能实现吗?IBATIS最成功的地方是实现SQL统一管理 一目了然,但是你这样写在JAVA里 眼都花了。
比如你定义了一个@Insert(id='xx',sql='sql') 然后在这这方法上调xxService.insert('xx') 那还不如把sql直接写在xxService.insert('sql')呢 那个ID完全是多余的东西。
以上属我的拙见 见笑了
我也用这样的思想封装过DAO
http://www.iteye.com/topic/232885 我现在项目里也一直在用。但是感觉ANNOTATION用多了未必是好事情,说明一下我用annotation进行DAO封装完全是让我的service不包含任何一个hibernate包下的任何一个类 不让使用的用户知道有HIBERNATE,只要会用ANNOTATION就好。它只是用来定义如何做查询 或者C U D的
49 楼 GandofYan 2008-10-15  
一直很喜欢iBatis

不过确实感觉annotation对于项目开发不太像是一个助力
48 楼 nextw3 2008-10-14  
感觉没什么必要,对于很多几乎不变的东西采用annotation比较好,而sql这种在开发中经常改动的东西也弄到annotation里,还不如不用他,直接代码里写SQL好。annotation是好东西,但是他不可能代替配置文件,他只是去除掉配置文件中必要的但开发中很少改变的东西。
47 楼 king_108 2008-10-14  
太强悍了,把XML的东西移植到JAVA类中,ORZ
46 楼 iKing 2008-10-13  
非常同意楼上的看法,感觉xml给了我们一个干净整洁的Java代码,而annotation又将这部分代码以另一种形式搬回到Java代码中,尤其是看到annotation这样的用法,实在让人望而却步啊。
45 楼 Readonly 2008-10-13  
cnoss 写道

上面这个Contact对象被用jpa、hibernate validator、hibernate search的标注描述过,难道我们会因为这样的“不优雅”而放弃使用吗?
不知道谁的奶酪被动了?不过这都只是个习惯的问题,世态总是在发展,不管它是直线型的还是螺旋型,如果你我改变不了,那最好的方式就是适应(当然,我们也可以放弃),适应的过程是痛苦的(如果你很在意自己一个人的感受),但最终的结果就是给了你我另一种习惯。呵呵,是吗,我的朋友?

越来越觉得Java的annotation是一个不实用的东西,特别是将这种原先分离得很干净的代码,混杂在一个文件里面,完全是在开倒车,还是坚持偶以前的观点:
http://www.iteye.com/post/505027
Readonly 写道

偶一直认为把annotation当作配置来用是一点好处也没有的,偶在实际项目中见过Model一个field上挂了O/R Mapping, Full Text Index, Validation, Security...整整超过10行的annotation,偶只不过是想看看这个Model有什么field而已,这样把整个一大包乱七八糟的annotation都塞在一个文件里面,不是一个大倒退么?


Readonly 写道

偶的意见就是要分开多个配置文件,减少Line Of Code per File,减少维护成本,降低出错概率,分离关注点。
44 楼 cnoss 2008-10-13  
没有,只是动态产生ibatis所需要的xml配置文件,并保存到临时文件中,然后载入这个临时文件,从而实现annotation到xml配置的转换,并在启动时完成对Ibatis的初始化工作。
43 楼 cuiyi.crazy 2008-10-13  
cnoss 写道
我的实现思路很简单,就是在启动时读取所有的dao对象的annotation信息,然后将其对应于Ibatis的sqlmapping,动态加载并生成ibatis的SqlMapClient,在没有修改Ibatis的前提下实现了annotation到xml的转换,所以是一次性装载的,不会重复读取。另外,我还封装了对事务的统一控制。

自定义类加载器classloader?
42 楼 cnoss 2008-10-12  
spaceflysky@163.com 写道
还是2个结合着用的好,适当的结合,各取所长,看具体应用的情况而定


是的,我很同意你的观点,各取所长,完美结合。
41 楼 spacefly 2008-10-12  
还行,不过觉得即使ibatis完全支持了注解,还是配置文件的方式比较的清晰!!!
还是2个结合着用的好,适当的结合,各取所长,看具体应用的情况而定
40 楼 cnoss 2008-10-11  
我的实现思路很简单,就是在启动时读取所有的dao对象的annotation信息,然后将其对应于Ibatis的sqlmapping,动态加载并生成ibatis的SqlMapClient,在没有修改Ibatis的前提下实现了annotation到xml的转换,所以是一次性装载的,不会重复读取。另外,我还封装了对事务的统一控制。
39 楼 cyberblue 2008-10-11  
问题不在于annotation本身,问题在于是否在部署时或第一次启动ORM引擎的时候能把字段到方法的Map一次性载入,避免重复读取。

大多数JPA软件已经做到了,但这个不知道做没做到。
38 楼 vdgame 2008-10-11  
我也是支持lz的,我是从c++、c#转到java开发的,当面对大量的xml配置时都快疯掉了。个人还是很喜欢annotation这种方式的,尤其是小项目,annotation太方便了。
37 楼 王者之剑 2008-10-11  
annotation这样用不服也不行
36 楼 redhacker 2008-10-11  
对于annotation的使用我同意lz的观点,看场合适度使用,不过目前看来annotation的普遍应用是一种趋势,我们应慢慢学会接受这种做法,习惯就好~~~

相关推荐

    struts2.1 spring2.5 ibatis2.3 dwr3 annotation配置 集成

    struts2.1 spring2.5 ibatis2.3 dwr3 annotation配置 集成 此中例子不完整. 如要下载:http://download.csdn.net/source/2138885

    spring2.5 ibatis2.3 struts2.1 dwr3 annotation集成配置

    本主题聚焦于一个经典的Java企业级应用架构:Spring 2.5、iBatis 2.3、Struts 2.1 和 DWR 3 的整合,以及使用注解(Annotation)进行配置。这四个组件的结合可以构建出一个功能强大、可扩展性好、易于维护的Web应用...

    Spring + Ibatis设置定时任务

    要启用Spring的定时任务,首先需要在Spring配置文件(如`applicationContext.xml`)中添加`&lt;task:annotation-driven/&gt;`元素,这将激活对`@Scheduled`注解的支持。如果需要自定义调度器,可以创建一个实现`Task...

    ibatis生成实体工具

    标题中的“ibatis生成实体工具”指的是一个辅助开发的软件或脚本,它能够自动生成基于iBatis框架的实体类(Entity Beans)和数据库操作的映射文件。iBatis是一个优秀的持久层框架,它将SQL语句与Java代码分离,提供...

    spring+ibatis集成文档

    INSERT INTO ibatis VALUES('2', '2'); ``` ##### 2.2 DAO接口定义 定义一个通用的数据访问层接口`IDAO`,用于处理基本的CRUD操作: ```java package ch10.SpringAndIbatis; import java.util.List; public ...

    spring 集成ibatis

    8. **性能优化**:iBatis 支持动态 SQL,可以根据条件灵活构建 SQL 语句,避免硬编码,提高代码可读性和性能。同时,Spring 提供的缓存机制也可以与 iBatis 结合,提高数据访问效率。 通过以上知识点的整合,我们...

    spring+ibatis声明式事务Demo

    在IT行业中,Spring框架与iBatis(现为MyBatis)是两个广泛使用的开源工具。Spring是一个全面的Java企业级应用开发框架,而iBatis(MyBatis)则是一个优秀的持久层框架,它简化了数据库操作。当我们谈论"spring+...

    spring ibatis 配置(包括事务管理)

    在整合Spring和iBatis框架时,我们需要进行一系列的配置工作,以便于让Spring负责管理iBatis的数据访问层。Spring作为一个强大的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)容器,可以方便地...

    spring_ibatis整合案例

    在IT行业中,Spring框架与iBatis(现为MyBatis)的整合是常见的数据访问层解决方案,尤其在企业级应用开发中极为普遍。Spring是一个全面的Java应用程序框架,提供了依赖注入、AOP(面向切面编程)、MVC(模型-视图-...

    spring+struts+ibatis用到的配置文件模板

    在实际应用中,Spring会作为容器管理Struts2的Action和iBatis的SqlSession,通过配置Spring的`&lt;bean&gt;`来注入Action和SqlSessionFactory。同时,Struts2的配置文件会引用Spring中的Bean来执行Action,iBatis的SQL查询...

    最简单的ibatis

    **Ibatis简介** Ibatis,一个轻量级的Java持久层...这就是Ibatis的基本使用方式,通过它,你可以轻松地管理和执行数据库操作,避免了直接操作JDBC带来的麻烦。Ibatis的简单易用性使其成为Java Web开发中的热门选择。

    简单的iBatis 实例

    2. **配置iBatis**:创建SqlMapConfig.xml文件,配置数据库连接信息,例如数据源、事务管理器等。例如: ```xml ``` 3. **编写Mapper XML 文件**:创建UserMapper.xml,定义SQL...

    ibatis 入门代码

    Ibatis支持动态SQL,可以通过`if`, `where`, `choose`, `when`, `otherwise`等标签实现条件判断,减少SQL拼接的麻烦。 **八、事务管理** Ibatis提供了基于Annotation的事务控制,可以结合Spring的@Transactional...

    ibatis SQL Map PPt

    Ibatis支持两种事务管理方式:手动事务和自动事务。手动事务需要开发者自己调用SqlSession的beginTransaction(), commit()和rollback()方法来控制事务的开始、提交和回滚。自动事务则可以通过配置 DataSource ...

    spring+ibatis

    标题 "spring+ibatis" 暗示了我们要探讨的是如何在Java开发中结合Spring框架与iBATIS(现在称为MyBatis)进行数据访问。Spring是一个全面的企业级应用框架,而MyBatis是一个轻量级的持久层框架,它简化了数据库操作...

    Spring+Ibatis集成开发实例.doc

    insert into ibatis values("2","2"); ``` 接下来,定义DAO(Data Access Object)接口,它是Java中的数据访问层接口,用于封装对数据库的操作。这里我们有一个名为`IDAO`的接口,包含获取列表、按名称或ID获取、...

    spring-mybatis-memcached.zip_Memcached java_annotation_mybatis_m

    因为 mybatis-memcached 不支持 MyBatis2(iBatis),只能用在 MyBatis3 里。但是因为有的项目还跑在 MyBatis2 版本上,所以也做一个例子。 mm-mybatis3-memcached 使用了 mybatis-memcached 。因为 simple-spring-...

    iBATIS SQL Maps

    6. **Transaction Management**:iBATIS支持JDBC和Spring两种事务管理方式,可以根据项目需求选择合适的方式进行配置。 7. **DAO(Data Access Object)接口**:在Java代码中,我们通常会创建一个DAO接口,然后通过...

    ibatis案例详解

    Ibatis 是一个轻量级的持久层框架,它与Java的ORM(对象关系映射)解决方案密切相关。在本文中,我们将深入探讨Ibatis的核心概念、配置以及如何通过一个实际案例来理解其工作原理。 首先,数据库脚本创建了一个名为...

    spring+springmvc+ibatis的整合例子

    在Java Web开发领域,Spring、SpringMVC和iBatis是三个非常重要的框架,它们的组合被称为SSM(Spring、SpringMVC、MyBatis)。SSM框架的整合使用能够帮助开发者实现高效、灵活和可扩展的Web应用程序。下面将详细讲解...

Global site tag (gtag.js) - Google Analytics