我们在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