仿Spring 的JdbcTemplate实现对数据库的CRUD操作

我们在jdbc程序时,会有大量的模板代码。这不得不使我们要去封装一些模板工具类来处理,在这个案例中我使用泛型封装了操作数据库的通用模板工具类,希望对初学者有用。

1. 创建数据库

此案例中使用mysql数据库。

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(25) CHARACTER SET utf8 DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  `money` float(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=UTF8;

2. 导入jar包

使用dbcp数据库,我们需要导入相关jar包。

3. 准备properties属性文件

#连接设置
#mysql database setting
jdbc.type=mysql
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username=root
password=123456

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
connectionProperties=useUnicode=true;characterEncoding=utf8

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

4. 定义JdbcUtils工具类

public class JdbcUtils {
	private static DataSource dataSource = null;
	
	//加载驱动
	static {
		try {
			Properties prop = new Properties();
			InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
			prop.load(in);
			//创建数据源对象
			dataSource = BasicDataSourceFactory.createDataSource(prop);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private JdbcUtils() {};
	
	//定义静态内部类
	private static class HolderClass {
		private final static JdbcUtils instance = new JdbcUtils();
	}
	
	public static JdbcUtils getInstance() {
		return HolderClass.instance;
	}
	
	//提供一个获取连接的方法
	public Connection getConnection() throws SQLException {
		return dataSource.getConnection();
	}
	
	//释放资源
	public void free(ResultSet rs, Statement st, Connection conn) {
		try {
			if (rs != null) {
				rs.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (st != null) {
					st.close();
				}
			} catch (SQLException e2) {
				e2.printStackTrace();
			} finally {
				if (conn != null) {
					try {
						//将用完的连接重写放回到连接池中
						conn.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

5. 创建JdbcTemplate模板对象

对于查询结果需要封装结果集,我们在此处定义一个接口,最终由调用该模板的方法实现该接口封装具体结果集数据。

5.1 定义RowMapper接口

public interface RowMapper<E> {
	E mapRow(ResultSet rs);
}

5.2 定义模板对象

在该模板对象中我只定义查询和更新的方法

public class JdbcTemplate {
	/*
	 * 查询方法
	 */
	public <T> T find(String sql, Object[] params, RowMapper<T> rowMapper) {
		Connection conn = null;
		PreparedStatement pst = null;
		ResultSet rs = null;
		try {
			conn = JdbcUtils.getInstance().getConnection();
			pst = conn.prepareStatement(sql);
			//设置参数
			for (int i = 0; i < params.length; i++) {
				pst.setObject(i + 1, params[i]);
			}
			rs = pst.executeQuery();
			T obj = null;
			if (rs.next()) {
				obj = rowMapper.mapRow(rs);
			}
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.getInstance().free(rs, pst, conn);
		}
		return null;
	}
	
	/**
	 * 查询返回集合
	 * @param sql
	 * @param params
	 * @param rowMapper
	 * @return
	 */
	public <T> List<T> findAll(String sql, Object[] params, RowMapper<T> rowMapper) {
		Connection conn = null;
		PreparedStatement pst = null;
		ResultSet rs = null;
		try {
			conn = JdbcUtils.getInstance().getConnection();
			pst = conn.prepareStatement(sql);
			if(params != null) {
				//设置参数
				for (int i = 0; i < params.length; i++) {
					pst.setObject(i + 1, params[i]);
				}
			}
			rs = pst.executeQuery();
			List<T> list = new ArrayList<>();
			while (rs.next()) {
				T obj = rowMapper.mapRow(rs);
				list.add(obj);
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.getInstance().free(rs, pst, conn);
		}
		return null;
	}
	
	/**
	 * 更新方法
	 * @param <T>
	 */
	public int update(String sql, Object[] params) {
		Connection conn = null;
		PreparedStatement pst = null;
		ResultSet rs = null;
		try {
			conn = JdbcUtilsSingleton.getInstance().getConnection();
			pst = conn.prepareStatement(sql);
			if (params != null) {
				//设置参数
				for (int i = 0; i < params.length; i++) {
					pst.setObject(i + 1, params[i]);
				}
			}
			return pst.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtilsSingleton.getInstance().free(rs, pst, conn);
		}
		return 0;
	}
	
}

6. 开发dao

6.1  定义接口

public interface UserDao {
	/**
	 * 新增用户
	 * 将参数设置为user对象
	 */
	void addUser(User user);
	
	/**
	 * 根据id查询user
	 */
	User getUserById(int id);
	
	/**
	 * 根据用户名查询用户
	 */
	User getUserByName(String username);
	
	/**
	 * 查询所有用户
	 * @return
	 */
	List<User> getAllUser();
	
	/**
	 * 更新用户
	 */
	void updateUser(User user);
	
	/**
	 * 删除用户
	 */
	void deleteUser(int id);
	
}

6.2  定义接口实现类

在实现类中我们只需要关心SQL语句和对应参数定义即可,使用起来非常方便。

public class UserDaoImpl implements UserDao {
	private JdbcTemplate jdbcTemplate = new JdbcTemplate();
	
	@Override
	public void addUser(User user) {
		String sql = "insert into t_user (username,birthday,money) values (?,?,?)";
		Object[] params = new Object[] {user.getUsername(), user.getBirthday(),user.getMoney()};
		jdbcTemplate.update(sql, params);
	}

	@Override
	public User getUserById(int id) {
		String sql = "select * from t_user where id = ?";
		Object[] params = new Object[] {id};
		User user = jdbcTemplate.find(sql, params, new UserMapper());
		return user;
	}

	@Override
	public User getUserByName(String username) {
		String sql = "select * from t_user where username = ?";
		Object[] params = new Object[] {username};
		User user = jdbcTemplate.find(sql, params, new UserMapper());
		return user;
	}

	@Override
	public void updateUser(User user) {
		String sql = "update t_user set username = ? where id = ?";
		Object[] params = new Object[] {user.getUsername(), user.getId()};
		jdbcTemplate.update(sql, params);
	}

	@Override
	public void deleteUser(int id) {
		String sql = "delete from t_user where id = ?";
		Object[] params = new Object[] {id};
		jdbcTemplate.update(sql, params);
	}

	@Override
	public List<User> getAllUser() {
		String sql = "select * from t_user";
		List<User> list = jdbcTemplate.findAll(sql, null, new UserMapper());
		return list;
	}
}

//定义结果处理的实现类
class UserMapper implements RowMapper<User> {

	@Override
	public User mapRow(ResultSet rs) {
		User user = new User();
		try {
			user.setId(rs.getInt("id"));
			user.setUsername(rs.getString("username"));
			user.setBirthday(rs.getDate("birthday"));
			user.setMoney(rs.getFloat("money"));
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return user;
	}
	
}

7.测试

/**
 * 
 * Description:测试类
 * @author: jzhang
 * CreateTime: 2019年1月23日上午10:18:45
 * Email: 1104975916@qq.com
 * 
 */
public class UserDaoTest {
	private UserDao userDao = null;
	
	@Before
	public void setUp() {
		userDao = new UserDaoImpl();
	}
	
	@Test
	public void testGetUserByName() {
		User user =  userDao.getUserByName("jack");
		System.out.println(user);
	}
	
	@Test
	public void testGetUserById() {
		User user =  userDao.getUserById(2);
		System.out.println(user);
	}
	
	@Test
	public void testGetAllUser() {
		userDao.getAllUser().forEach(System.out::println);
	}
	
	@Test
	public void testUpdateUser() {
		User user = new User();
		user.setId(3);
		user.setUsername("老王");
		userDao.updateUser(user);
	}
	
	@Test
	public void testdeleteUser() {
		userDao.deleteUser(9);
	}
	
	@Test
	public void testaddUser() {
		User user = new User("蓝莲花", new Date(), 1000);
		userDao.addUser(user);
	}
}

最后

作者:edwarder

交流群:790786964

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

章老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值