DAO
学习dao前有数据库基础,java与数据库连接使用的是jdbc,在此前我已学习过jdbc也不再介绍jdbc,直接使用Spring的DAO模块,而在使用Spring的DAO,最基础的DAO模块对JDBC的支持。依赖于commons-dbcp.jar和commons-pool.jar。在pox中新添依赖。
org.springframework
spring-jdbc
4.2.6.RELEASE
commons-dbcp
commons-dbcp
1.4
commons-pool
commons-pool
1.6
mysql
mysql-connector-java
5.1.6
在传统的JDBC中需要创建连接、打开、执行SQL、关闭连接一系列的步骤,Spring对JDBC进行了封装,我们只需使用封装好的JdbcTemplate执行SQL语句就可以了。通过JdbcDaoSupport获取JdbcTemplate对象。
DAO的学习使用mysql,通过下语句新建一个数据库并插入5个值。
USE test;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`money` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=gbk;
INSERT INTO `t_user` VALUES ('1', '张三', '24', '666.66');
INSERT INTO `t_user` VALUES ('2', '李四', '25', '888.88');
INSERT INTO `t_user` VALUES ('3', '王二', '26', '999.99');
INSERT INTO `t_user` VALUES ('4', '小明', '27', '555.55');
INSERT INTO `t_user` VALUES ('5', '小赵', '28', '333.33');
一、JdbcDaoSupport的使用
该例实现了对上述创建的数据库进行输出和插入的功能。
1、User类
新建User类,定义类字段与数据库字段对应,并声明构造函数。
public class User {
@Override
public String toString(){
return "Id:"+this.getId()+" Name:"+this.getName()
+" Age:"+this.getAge()+" Money:"+this.getMoney();
}
private int Id;
private String Name;
private int Age;
private double Money;
public User(){}
public User(String name,int age,double money){
Name = name;
Age = age;
Money = money;
}
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public double getMoney() {
return Money;
}
public void setMoney(double money) {
Money = money;
}
}
2、IUserDAO接口
QueryAllUser方法查询数据库所有信息,AddUser为插入信息操作。
public interface IUserDAO {
public List QueryAllUser();
public Boolean AddUser(User user);
}
3、Xml配置
配置了数据库源,数据库用户和密码,因为SpringDAODemo中继承了JdbcDaoSupport,所以要设置dapends-on,这样才能从数据源中操作。
com.mysql.jdbc.Driver
jdbc:mysql://127.0.0.1:3306/test
root
951753
4、SpringDAODemo
程序入口类,并继承JdbcDaoSupport和实现IUserDAO接口中的方法。从JdbcDaoSupport中获取JdbcTemplate对象,使用queryForList方法进行sql查询,使用update方法进行sql更新。
在获取查询结果时,是将查询结果中的各行放到一个Map中,再将各个Map放到List中。因此得到结果后还需转化成List
public class SpringDAODemo extends JdbcDaoSupport implements IUserDAO {
public static void main (String [] args){
ApplicationContext context =
new ClassPathXmlApplicationContext("DAO/app.xml");
IUserDAO userDAO = (IUserDAO)context.getBean("userDao");
User user = new User("JdbcDaoSupportTest",26,333.33);
userDAO.AddUser(user);
List list = userDAO.QueryAllUser();
for(User u:list){
System.out.println(u.toString());
}
}
@Override
public List QueryAllUser() {
String sql = "select id,name,age,money from t_user order by id desc";
List
运行结果
Id:1 Name:张三 Age:24 Money:666.66
Id:2 Name:李四 Age:25 Money:888.88
Id:3 Name:王二 Age:26 Money:999.99
Id:4 Name:小明 Age:27 Money:666.66
Id:5 Name:小赵 Age:28 Money:333.33
Id:6 Name:JdbcDaoSupportTest Age:26 Money:333.33
二、MappingSqlQuery的使用
刚刚的JdbcDaoSupport的使用是获取一个List
MappingSqlQuery是一个抽风象类,在使用他时需要实现它的方法mapRow。
这里相当于将JdbcDaoSupport中的Map
public class UserMappingSqlQuery extends MappingSqlQuery {
@Override
protected User mapRow(ResultSet resultSet, int i) throws SQLException {
User user = new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name"));
user.setAge(resultSet.getInt("age"));
user.setMoney(resultSet.getDouble("money"));
return user;
}
}
在使用UserMappingSqlQuery时,需要传入DataSource和sql,然后执行compile编译。可以直接通过getDataSource()
来获取到JdbcDaoSupport的DataSource属性。在sql语句中如果有类似预处理的?参数,可以使用setParameters()
设置参数。
下面将原本SpringDAODemo.QueryAllUser()方法修改,输出表中全部信息的功能不变。返回为List
@Override
public List QueryAllUser() {
String sql = "select id,name,age,money from t_user where name=? or ?";
UserMappingSqlQuery userQuery = new UserMappingSqlQuery();
userQuery.setDataSource(getDataSource());
userQuery.setSql(sql);
userQuery.setParameters(new SqlParameter[]{
new SqlParameter(Types.VARCHAR)
,new SqlParameter(Types.VARCHAR)
});
userQuery.compile();
return userQuery.execute(new Object[]{"1","1=1"});
}
将方法替换后,执行结果与使用JdbcDaoSupport结果一致。
三、SqlUpdate的使用
SqlUpdate主要用来更新,将某个功能模块化。下例中,通过构造函数设置必须的参数,再使用updateUserMoney调用继承的update函数来更新数据。
public class UserSqlUpdate extends SqlUpdate {
public static void main(String [] args){
ApplicationContext context = new ClassPathXmlApplicationContext("DAO/app.xml");
UserSqlUpdate userSqlUpdate = (UserSqlUpdate)context.getBean("userSqlUpdate");
userSqlUpdate.updateUserMoney("小明",666.66);
}
public UserSqlUpdate(DataSource ds){
setDataSource(ds);
setSql("update t_user set money=? where name=?");
declareParameter(new SqlParameter(Types.DOUBLE));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
public Boolean updateUserMoney(String name,double money){
int row = update(new Object[]{new Double(money), name});
if(row>0){
System.out.println("money更改成功");
return true;
}
return false;
}
}
xml配置中为userSqlUpdata配置。
四、Spring事务管理
Spring中的事务管理是将DataSourceTransactionManager作为JDBC的事务管理者,同时把被管理的对象使用TransactionProxyFactoryBean配置,使用的也是代理模式。
用转账来示例事务管理,在IUserDAO接口中增加转账方法transfer
public Boolean transfer(int fromUserId,int toUserId, float transferMoney);
在SpringDAODemo类中实现transfer,从fromUserId中扣钱增加到toUserId中。其中有一个人为的制作的错误int i = 1/0
被注释。
@Override
public Boolean transfer(int fromUserId, int toUserId, float transferMoney) {
Boolean out = outInMoney(fromUserId,-transferMoney);
// int i = 1/0;
Boolean in = outInMoney(toUserId,transferMoney);
return out∈
}
private Boolean outInMoney(int toUserId,float money){
String sql = "update t_user set money=money+? where id=?";
int row = getJdbcTemplate().update(sql,new Object[]{money,toUserId});
if(row>0){
return true;
}
return false;
}
xml中配置管理事务,代理模式的注入我们已经很熟悉,这里是创建一个事务管理者,然后将事务管理者和被管理的对象注入到TransactionProxyFactoryBean中生成代理对象。在xml中增加以下代码。
PROPAGATION_REQUIRED
注意事务属性PROPAGATION_REQUIRED的意义。
假如当前正要执行的事务不在另外一个事务里,那么就起一个新的事务。
因为扣钱和加钱都在同一个方法中,这时两个事务实际在同一个事务中。若在方法transfer第一次事务发生前,并无事务,在扣钱时,这时事务已经产生,并在第二次操作进行加钱时进行事务判断,已有事务并在同一个事务中,这时将第二次操作添加到已有事务。方法结束该事务结束。当在该事务中发生任何异常,将回滚已在该事务中的任何操作。
main
public static void main (String [] args){
ApplicationContext context = new ClassPathXmlApplicationContext("DAO/app.xml");
IUserDAO userDAO = (IUserDAO)context.getBean("userDaoProxy");
try{
userDAO.transfer(1,2,100);
}catch (Exception e){
e.printStackTrace();
System.out.println("事务回滚");
}
}
成功将张三的钱转账给李四。当发生事务回滚时,转账会被回滚
Id:6 Name:JdbcDaoSupportTest Age:26 Money:333.33
Id:5 Name:小赵 Age:28 Money:333.33
Id:4 Name:小明 Age:27 Money:666.66
Id:3 Name:王二 Age:26 Money:999.99
Id:2 Name:李四 Age:25 Money:988.88
Id:1 Name:张三 Age:24 Money:566.66