标准的Java DAO写法:
- 定义DAO接口;
- 编写DAO实现类;
- 在实现类中编写JDBC代码。
写JDBC代码非常枯燥而且容易出错,因此,增强的DAO可以用类似Spring的JdbcTemplate简化JDBC代码,不过仍然需要大量的ConnectionCallback,PreparedStatementCallbac等。
如果仅定义DAO接口,并利用Java 5 Annotation写好SQL语句,其余的工作全部由底层框架完成:
- 自动将接口方法的参数绑定到SQL的参数;
- 自动将ResultSet映射到Object;
- ...
现在,利用Express Persistence,完全可以实现!
让我们用Express Persistence实现一个完整的DAO:
假定数据库表User包含字段如下:
id varchar(32) primary key, name varchar(50) not null, gender bit not null, age int not null.并且定义好JavaBean TestUser:
public class TestUser {
private String id;
private String name;
private boolean gender;
private int age;
// getters and setters here...
}
现在,我们就可以定义TestUserDao接口了:
public interface TestUserDao {
@Unique
@MappedBy(TestUserRowMapper.class)
@Query("select * from User u where u.id=:id")
TestUser queryById(@Param("id") String id);
@MappedBy(TestUserRowMapper.class)
@Query("select * from User u order by u.id")
List<TestUser> queryAll();
@MappedBy(TestUserRowMapper.class)
@Query("select * from User u order by u.id")
List<TestUser> queryFrom(@FirstResult int first);
@MappedBy(TestUserRowMapper.class)
@Query("select * from User u order by u.id")
List<TestUser> queryMax(@MaxResults int max);
@MappedBy(TestUserRowMapper.class)
@Query("select * from User u order by u.id")
List<TestUser> queryRange(@FirstResult int first, @MaxResults int max);
@Update("insert into User(id, name, gender, age) values(:id, :name, :gender, :age)")
void createUser(@Param("id") String id, @Param("name") String name, @Param("gender") boolean gender, @Param("age") int age);
@Update("update User set name=:name where id=:id")
int updateUserName(@Param("id") String id, @Param("name") String name);
@Update("delete from User where id=:id")
int deleteUser(@Param("id") String id);
}
注意到@Query和@Update,SQL语句直接写在里面。为了让SQL参数和方法参数绑定,必须使用:xxx标记SQL参数,并为方法参数标记对应的@Param("xxx")。(有点麻烦,难道不能直接通过方法参数名字绑定?哈哈,编译后的.class就只有类型没有名字了)
例如,更新UserName的SQL语句:
update User set name=:name where id=:id
对应的绑定参数是:name和:id,因此方法参数要这么写:
int updateUserName(@Param("id") String id, @Param("name") String name);
没有实现类?没错,不需要实现类,我们就可以直接使用:
public static void main(String[] args) throws Exception {
// get data source from somewhere:
DataSource dataSource = ...
// create TransactionManager and DAOFactory:
JdbcTransactionManager txManager = new JdbcTransactionManager(dataSource);
JdbcDaoFactory daoFactory = new JdbcDaoFactory(new HSQLDBDialect());
// now create DAO:
TestUserDao dao = daoFactory.createDao(TestUserDao.class, txManager);
// ok, now we can do CRUD by DAO now, but need transaction support:
Transaction tx = txManager.beginTransaction();
try {
// create 10 user:
for (int i=0; i<10; i++)
dao.createUser("123456789012345678901234567890f" + i, "name-" + i, true, 20 + i);
// query users with offset and limit:
List<TestUser> users = dao.queryRange(3, 5);
// print user name, the output should be:
// name-3
// name-4
// name-5
// name-6
// name-7
for (TestUser user : users)
System.out.println(user.getName());
// delete user with name 'name-3':
int n = dao.deleteUser(users.get(0).getId());
System.out.println(n + " user deleted.");
tx.commit();
}
catch(Exception e) {
if (! tx.isRollbackOnly())
tx.rollback();
}
catch(Error e) {
if (! tx.isRollbackOnly())
tx.rollback();
}
}
核心代码:
TestUserDao dao = daoFactory.createDao(TestUserDao.class, txManager);
通过DaoFactory,我们得到一个实现了TestUserDao接口的实例,通过该实例,直接操作数据库!