文章目录
- 3.Spring框架 控制反转(IOC)/依赖注入(DI)实战
- 3.1 优化现有的CURD流程
- 3.2 Spring+Dbutils实现CURD操作
3.Spring框架 控制反转(IOC)/依赖注入(DI)实战
3.1 优化现有的CURD流程
需求说明 : 引入Spring优化现有开发流程,完成user_info表的CURD操作
完成数据库表的CURD操作,步骤无外乎就几步
- 创建实体类
- 编写数据库连接工具类
- DAO层完成数据库SQL语句的封装
- 业务层处理可以业务数据
所以我们就按照步骤实现即可
3.2 Spring+Dbutils实现CURD操作
数据库 : userdb
3.2.1 表 :
CREATE TABLE `user_info` (
`u_id` int(8) NOT NULL auto_increment,
`u_name` varchar(32) default NULL,
`u_regdate` date default NULL,
`u_money` double default NULL,
PRIMARY KEY (`u_id`)
)
3.2.2 创建项目,导入jar包
3.2.3 创建Spring的配置文件,applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
创建各层的包,依次编写
3.2.4 实体类 :
package com.hnxy.entity;
import java.util.Date;
/**
* 用户表的实体类
* @author sysmaster
*
*/
public class UserInfo {
// 私有属性
private Integer uid; // 主键ID
private String uname; // 客户姓名
private Date regDate; // 注册日期
private Double money; // 存款
// 共有方法
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Date getRegDate() {
return regDate;
}
public void setRegDate(Date regDate) {
this.regDate = regDate;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "UserInfo [uid=" + uid + ", uname=" + uname + ", regDate=" + regDate + ", money=" + money + "]";
}
}
3.3.6 DAO层接口,固定六个方法
package com.hnxy.dao;
import java.util.List;
import com.hnxy.entity.UserInfo;
/**
* DAO层的6个方法
* @author sysmaster
*
*/
public interface UserDAO {
/**
* 添加
* @param user
* @return
* @throws Exception
*/
public int insertUser(UserInfo user)throws Exception;
/**
* 更新
* @param user
* @return
* @throws Exception
*/
public int updateUser(UserInfo user)throws Exception;
/**
* 删除
* @param user
* @return
* @throws Exception
*/
public int deleteUser(UserInfo user)throws Exception;
/**
* 按ID查询
* @param uid
* @return
* @throws Exception
*/
public UserInfo findUserByID(Integer uid)throws Exception;
/**
* 分页展示
* @param start
* @param end
* @return
* @throws Exception
*/
public List<UserInfo> findUserListByPage(Integer start,Integer end)throws Exception;
/**
* 获取数据总条数
* @return
* @throws Exception
*/
public int findUserListByPageCount()throws Exception;
}
3.3.7 DAO层实现类优化方案 :
以前我们肯定是需要编写一个数据库连接驱动类来获取连接,现在有了spring就不用了,我们可以直接在spring配置文件applicationContext.xml里创建数据库连接
3.3.7.1 创建数据源 :
<!-- 创建数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/userdb?characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
这些属性都是我们根据之前在jdbcutil中的设置转化而来的,通过这些属性Spring就能帮助我们创建一个数据源了
3.3.7.2 创建SQL的执行对象
其实不光是数据源 我们的queryRunner对象也可以放在spring配置文件中创建
<!-- 创建SQL执行对象 -->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner"></bean>
此处我们除了创建QueryRunner对象之外还能够将他与数据源关联,因为根据源码可以知道qr在创建的时候可以关联数据源,关联数据源之后我们就不用在
调用qr的query或者update方法的时候设定conn了
3.3.7.3 源码
所以我们可以通过构造注入完成这个数据源对象的注入
<!-- 创建SQL执行对象 -->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource" />
</bean>
这样我们就有了一个QueryRunner对象
但是大家要注意一个问题就是QueryRunner是负责执行SQL语句的对象,Spring创建这个对象的时候会以单例模式创建这个对象,那么这时就有一个问题了
单例对象在多线程环境下只有一个实例对象,这时候大家(多个线程)都使用这一个QueryRunner执行SQL语句势必会造成线程阻塞问题,而且在执行一些包含有事务的操作
3.3.7.4 多线程问题
如果多个线程共享一个QueryRunner对象似乎也不太安全,所以这个时候我们就想能不能用多例创建这个对象呢?
当然可以,在bean标签中加入scope属性即可
<!-- 创建SQL的执行对象 -->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource" />
</bean>
通过 scope=“prototype” 的设置,Spring在创建这个对象的时候就是多例创建了
默认情况下spring创建的对象都是单例的 所以通过bean的scope属性可以改变创建对象的策略
如果 scope=“singleton” 的时候(默认情况)spring就会以单例模式创建
如果scope=“prototype” 的时候 spring就会以多例创建这个对象
3.3.7.4.1 多例配置测试
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
QueryRunner qr1 = context.getBean(QueryRunner.class);
QueryRunner qr2 = context.getBean(QueryRunner.class);
System.out.println(qr1);
System.out.println(qr2);
}
3.3.7.4.2 单例配置测试
<!-- 创建SQL执行对象 -->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource" />
</bean>
那么这时候有的同学就会想,QueryRunner是多例的其他的对象要不要也多例呢?
这个问题就需要根据你们公司的具体业务来实现了,因为多例与单例模式创建对象各有优缺点,所以不能一概而论用哪个更好,
必须根据实际业务需要来就好比我们这个qr对象一样,我们是因为怕多线程阻塞 所以采用的多例
举个例子,
银行有一台ATM,每天来取钱的由5个人,这时候虽然可能5个人都来的时候会等一会但是时间不长,可以忍受,这时候一台ATM就可以 这就是单例
但是如果每天都有500个人来取钱,那么一台ATM肯定是不够的,所以就需要增加ATM的数量 这就是多例
所以 单例或者多例的设置必须根据业务逻辑来实现!
我们已经设置好了QueryRunner,那么大家想一想谁会用到这个对象呢?
是DAO的实现类!所以DAO实现类中如果想使用这个对象就可以这么写
public class UserDAOImpl implements UserDAO {
// 创建数据库的执行对象
private QueryRunner qr;
// Spring值注入
public void setQr(QueryRunner qr) {
this.qr = qr;
}
.......其他代码省略
}
说完了对jdbcUtil的改造之后我们继续完成
3.3.8 DAO层接口实现
数据库对象都交给spring了所以此处我们只关心操作就可以了
package com.hnxy.dao.impl;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.hnxy.dao.UserDAO;
import com.hnxy.entity.UserInfo;
public class UserDAOImpl implements UserDAO {
private QueryRunner qr;
public void setQr(QueryRunner qr) {
this.qr = qr;
}
@Override
public int insertUser(UserInfo user) throws Exception {
// 创建方法的返回值
int count = 0;
// 编写SQL语句
String sql = "insert into user_info values (null,?,?,?)";
// 占位符赋值
Object[] params = {user.getUname(),user.getRegDate(),user.getMoney()};
// 执行
count = qr.update(sql, params);
// 返回
return count;
}
@Override
public int updateUser(UserInfo user) throws Exception {
// 创建方法的返回值
int count = 0;
// 编写SQL语句
String sql = "update user_info set `u_name`=?,`u_regdate`=?,`u_money`=? where `u_id`=?";
// 占位符赋值
Object[] params = {user.getUname(),user.getRegDate(),user.getMoney(),user.getUid()};
// 执行
count = qr.update(sql, params);
// 返回
return count;
}
@Override
public int deleteUser(UserInfo user) throws Exception {
// 创建方法的返回值
int count = 0;
// 编写SQL语句
String sql = "delete from user_info where `u_id` = ?";
// 占位符赋值
Object[] params = {user.getUid()};
// 执行
count = qr.update(sql, params);
// 返回
return count;
}
@Override
public UserInfo findUserByID(Integer uid) throws Exception {
// 创建方法的返回值
UserInfo user = null;
// 编写SQL语句
String sql = "select * from v1 where `uid` = ?";
// 占位符赋值
Object[] params = {uid};
// 执行
user = qr.query(sql, new BeanHandler<UserInfo>(UserInfo.class),params);
// 返回
return user;
}
@Override
public List<UserInfo> findUserListByPage(Integer start, Integer end) throws Exception {
// 创建方法的返回值
List<UserInfo> list = null;
// 创建SQL语句
String sql = "select * from v1 limit ?,?";
// 占位符赋值
Object[] params = {start,end};
// 执行
list = qr.query(sql, new BeanListHandler<UserInfo>(UserInfo.class),params);
// 返回
return list;
}
@Override
public int findUserListByPageCount() throws Exception {
// 创建方法的返回值
int totalCount = 0;
// 编写SQL语句
String sql = "select count(*) from v1";
// 占位符赋值
// 执行
Number num = qr.query(sql, new ScalarHandler<Number>());
// 设定返回值
totalCount = num.intValue();
// 返回
return totalCount;
}
}
3.3.9 在spring中配置UserDAOImpl的对象applicetionContext.xml
在spring中配置UserDAOImpl的对象applicetionContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 1.创建数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/userdb?characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- 2.创建SQL执行对象 -->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource" />
</bean>
<!-- 3.创建DAO对象 -->
<bean id="userDAO" class="com.hnxy.dao.impl.UserDAOImpl">
<property name="qr" ref="qr" />
</bean>
</beans>
3.3.10 测试类
package com.hnxy.test;
import java.util.Date;
import java.util.List;
import java.util.Random;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.hnxy.dao.UserDAO;
import com.hnxy.entity.UserInfo;
public class Test1 {
private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
private UserDAO userDAO = context.getBean(UserDAO.class);
public void addTest()throws Exception{
// 添加测试
UserInfo user = null;
Random random = new Random();
for (int i = 1; i <= 100; i++) {
user = new UserInfo();
user.setUname("用户"+i);
user.setMoney(random.nextInt(50000)+0D);
user.setRegDate(new Date(System.currentTimeMillis()+1000*60*60*24*random.nextInt(366)));
int count = userDAO.insertUser(user);
System.out.println(count);
}
}
public void updateTest()throws Exception{
// 测试更新
UserInfo user = userDAO.findUserByID(64);
if(null != user){
// 开始更新
user.setUname("赵文明");
user.setMoney(88888D);
user.setRegDate(new Date());
int count = userDAO.updateUser(user);
String msg = count>0?"更新成功":"更新失败";
System.out.println(msg);
}else{
System.out.println("没有找到要更新的数据!");
}
}
public void deleteTest()throws Exception{
// 测试删除
UserInfo user = userDAO.findUserByID(65);
if(null != user){
// 开始删除
int count = userDAO.deleteUser(user);
String msg = count>0?"删除成功":"删除失败";
System.out.println(msg);
}else{
System.out.println("没有找到要删除的数据!");
}
}
@Test
public void queryTest()throws Exception{
// 分页测试
// 定义分页属性
int totalCount = 0;
int totalPage = 0;
int pageIndex = 1;
int pageSize = 10;
// 获取总条数
totalCount = userDAO.findUserListByPageCount();
// 计算总页数
totalPage = totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
// 输出
System.out.println("共查询出" + totalCount + "条数据,每页展示" + pageSize + "条,一共展示" + totalPage + "页,当前为第" + pageIndex + "页");
// 获取数据集合
List<UserInfo> list = userDAO.findUserListByPage((pageIndex-1)*pageSize, pageSize);
// 循环展示
for (UserInfo userInfo : list) {
System.out.println(userInfo);
}
}
}
DAO层完成,正常整理Service层即可
3.3.11 Service接口
package com.hnxy.service;
import java.util.List;
import com.hnxy.entity.UserInfo;
/**
* 用户表的业务层接口
* @author sysmaster
*
*/
public interface UserService {
/**
* 添加
* @param user
* @return
* @throws Exception
*/
public int insertUser(UserInfo user)throws Exception;
/**
* 更新
* @param user
* @return
* @throws Exception
*/
public int updateUser(UserInfo user)throws Exception;
/**
* 删除
* @param user
* @return
* @throws Exception
*/
public int deleteUser(UserInfo user)throws Exception;
/**
* 按ID查询
* @param uid
* @return
* @throws Exception
*/
public UserInfo findUserByID(Integer uid)throws Exception;
/**
* 分页展示
* @param start
* @param end
* @return
* @throws Exception
*/
public List<UserInfo> findUserListByPage(Integer start,Integer end)throws Exception;
/**
* 获取数据总条数
* @return
* @throws Exception
*/
public int findUserListByPageCount()throws Exception;
}
3.3.12 Service实现类
package com.hnxy.service.impl;
import java.util.List;
import com.hnxy.dao.UserDAO;
import com.hnxy.entity.UserInfo;
import com.hnxy.service.UserService;
public class UserServiceImpl implements UserService {
// 声明DAO层对象
private UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
@Override
public int insertUser(UserInfo user) throws Exception {
return userDAO.insertUser(user);
}
@Override
public int updateUser(UserInfo user) throws Exception {
return userDAO.updateUser(user);
}
@Override
public int deleteUser(UserInfo user) throws Exception {
return userDAO.deleteUser(user);
}
@Override
public UserInfo findUserByID(Integer uid) throws Exception {
return userDAO.findUserByID(uid);
}
@Override
public List<UserInfo> findUserListByPage(Integer start, Integer end) throws Exception {
return userDAO.findUserListByPage(start, end);
}
@Override
public int findUserListByPageCount() throws Exception {
return userDAO.findUserListByPageCount();
}
}
3.3.13 spring配置Service对象applicetionContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 创建数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/userdb?characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- 创建SQL执行对象 -->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<constructor-arg name="ds" ref="dataSource" />
</bean>
<!-- 创建DAO对象 -->
<bean id="userDAO" class="com.hnxy.dao.impl.UserDAOImpl">
<property name="qr" ref="qr" />
</bean>
<!-- 创建Service对象 -->
<bean id="userService" class="com.hnxy.service.impl.UserServiceImpl">
<property name="userDAO" ref="userDAO" />
</bean>
</beans>
至此Spring引入CURD项目完成