Java之JDBC连接数据库实现增删改查(2018 使用Dao层实现 完美封装解决硬编码问题)

版权声明:《==study hard and make progress every day==》 https://blog.csdn.net/qq_38225558/article/details/82843095

项目结构层次图:

数据库名:zhengqing_test                  表t_user  

配置文件 db.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/zhengqing_test
username=root
password=root

用户账号实体类 User.java

/**
 * 用户账号实体类
 * @author 郑清
 */
public class User {
	
	private int id;
	private String username;
	private String password;
	
	public User() {}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
	}
	
}

接口类 IUserDao.java

/**
 * 接口类
 * @author 郑清
 */
public interface IUserDao {
	void add(User user);
	void delete(int id);
	void update(User user);
	User queryOne(int id);
	List<User> queryAll();
}

工具类 JDBCUtil.java

/**
 * 工具类:
 * 抽取公共部分,做单例模式
 * @author 郑清
 */
public enum JDBCUtil {
	
	instance;
	private static Properties p = new Properties();
	
	//加载驱动 
	static {//当用到该工具类的时候,会自动加载驱动
		try {
			//读取配置文件db.properties
			p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
			//System.out.println(pro.getProperty("driverClassName"));
			//加载驱动
			Class.forName(p.getProperty("driverClassName"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	//获取连接:与数据库建立连接
	public Connection getConnection(){//没有static:应该通过对象调用该方法
		try {
			return DriverManager.getConnection(p.getProperty("url"), p.getProperty("username"), p.getProperty("password"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	//释放资源   (注意:关闭资源顺序 先打开后关闭)
	public void close(Connection connection,Statement statement,ResultSet rs){
		try {
			if(rs!=null)rs.close();
		} catch (SQLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}finally{
			try {
				if(statement!=null)statement.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				try {
					if(connection!=null)connection.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
}

实现接口类 UserDaoImpl.java

/**
 * 实现接口IUserDao
 * 使用预编译对象 PreparedStatement实现增删改查,特点:创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译
 * @author 郑清
 */
public class UserDaoImpl implements IUserDao {
	
	@Override
	public void add(User user) {
		// TODO Auto-generated method stub
		Connection connection = null;
		PreparedStatement ps = null;
		try {
			//1.加载驱动
			//2.获取连接:与数据库建立连接
			connection = JDBCUtil.instance.getConnection();
			//3.使用预编译对象 PreparedStatement实现添加,特点:创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译
			//4.执行sql语句    (注意:当3.中编译语句执行的时候不需要传sql dbms会直接运行编译后的sql语句)
			String sql = "insert into t_user(username,password) values (?,?);";// ? ==> 占位符
			ps = connection.prepareStatement(sql);
			ps.setString(1, user.getUsername());//占位符?从1开始
			ps.setString(2, user.getPassword());
			ps.executeUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//5.释放资源      (注意:关闭资源顺序 先打开后关闭)
			JDBCUtil.instance.close(connection, ps, null);
		}	
	}

	@Override
	public void delete(int id) {
		// TODO Auto-generated method stub
		Connection connection = null;
		PreparedStatement ps = null;
		try {
			//1.加载驱动
			//2.获取连接:与数据库建立连接
			connection = JDBCUtil.instance.getConnection();
			//3.使用预编译对象 PreparedStatement实现删除,特点:创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译
			//4.执行sql语句    (注意:当3.中编译语句执行的时候不需要传sql dbms会直接运行编译后的sql语句)
			String sql = "delete from t_user where id = ? ;";// ? ==> 占位符
			ps = connection.prepareStatement(sql);
			ps.setInt(1, id);//占位符?从1开始
			ps.executeUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//5.释放资源      (注意:关闭资源顺序 先打开后关闭)
			JDBCUtil.instance.close(connection, ps, null);
		}
	}

	@Override
	public void update(User user) {
		// TODO Auto-generated method stub
		Connection connection = null;
		PreparedStatement ps = null;
		String sql = "update t_user set username = ? , password = ? where id = ? ;";// ? ==> 占位符
		try {
			//1.加载驱动
			//2.获取连接:与数据库建立连接
			connection = JDBCUtil.instance.getConnection();
			//3.使用预编译对象 PreparedStatement实现更新,特点:创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译
			//4.执行sql语句    (注意:当3.中编译语句执行的时候不需要传sql dbms会直接运行编译后的sql语句)
			ps = connection.prepareStatement(sql);
			ps.setString(1,user.getUsername());//占位符?从1开始
			ps.setString(2,user.getPassword());
			ps.setInt(3,user.getId());
			ps.executeUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//5.释放资源      (注意:关闭资源顺序 先打开后关闭)
			JDBCUtil.instance.close(connection, ps, null);
		}
	}
	
	@Override
	public User queryOne(int id) {
		// TODO Auto-generated method stub
		Connection connection = null;
		PreparedStatement ps = null;
		String sql = "select * from t_user where id = ? ;";
		ResultSet rs = null;
		User user = null;
		try {
			//1.加载驱动
			//2.获取连接:与数据库建立连接
			connection = JDBCUtil.instance.getConnection();
			//3.使用预编译对象 PreparedStatement实现查找,特点:创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译
			//4.执行sql语句    (注意:当3.中编译语句执行的时候不需要传sql dbms会直接运行编译后的sql语句)
			ps = connection.prepareStatement(sql);
			ps.setInt(1, id);//占位符?从1开始
			rs = ps.executeQuery();
			while(rs.next()) {
				user = new User();
				user.setId(rs.getInt("id"));
				user.setUsername(rs.getString("username"));
				user.setPassword(rs.getString("password"));
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//5.释放资源      (注意:关闭资源顺序 先打开后关闭)
			JDBCUtil.instance.close(connection, ps, rs);
		}
		return user;
	}

	@Override
	public List<User> queryAll() {
		// TODO Auto-generated method stub
		//1.加载驱动
		//2.获取连接:与数据库建立连接
		Connection connection = JDBCUtil.instance.getConnection();
		PreparedStatement ps = null;
		String sql = "select * from t_user;";
		ResultSet rs = null;
		List<User> userList = new ArrayList<>();
		try {
			//3.使用预编译对象 PreparedStatement实现查找,特点:创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译
			//4.执行sql语句    (注意:当3.中编译语句执行的时候不需要传sql dbms会直接运行编译后的sql语句)
			ps = connection.prepareStatement(sql);
			rs = ps.executeQuery();
			while(rs.next()){
				User user = new User();
				user.setId(rs.getInt("id"));
				user.setUsername(rs.getString("username"));
				user.setPassword(rs.getString("password"));
				userList.add(user);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//5.释放资源      (注意:关闭资源顺序 先打开后关闭)
			JDBCUtil.instance.close(connection, ps, rs);
		}
		return userList;
	}

}

测试类 UserDaoTest.java

/**
 * 使用Junit4测试 数据库的增删改查
 * @author 郑清
 */
public class UserDaoTest {
	
	UserDaoImpl userDao = new UserDaoImpl();
	
	@Test
	public void testAdd() {
		User user = new User();
		user.setUsername("小猪佩奇");
		user.setPassword("123456");
		userDao.add(user);
	}
	
	@Test
	public void testUpdate(){
		User user = new User();
		user.setId(13);
		user.setUsername("大熊");
		user.setPassword("488646");
		userDao.update(user);
	}
	
	@Test
	public void testDelete(){
		userDao.delete(16);
	}
	
	@Test
	public void testQueryOne(){
		User user = userDao.queryOne(3);
		System.out.println(user);
	}
	
	@Test
	public void testQueryAll(){
		List<User> users = userDao.queryAll();
		for (User user : users) {
			System.out.println(user);
		}
	}
	
}

获得sql的预编译对象   (使用Statement ==>特点:在执行的时候,才会将sql发送到 dbms进行编译)

点击到csdn资源中心直接下载

点击下载资源(Statement版)    密码:0t7n    (百度云盘)


使用预编译对象 PreparedStatement实现增删改查,特点:创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译

点击到csdn资源中心直接下载

点击下载资源(PreparedStatement版)     密码:ya4n   (百度云盘)


注意:这里我们应该选择PreparedStatement版

================why??==================

PreparedStatement 安全,便捷不需要我们去拼接字符串,特别是字段很多的时候

PreparedStatemnt的效率更高

PrepareStatement是预编译语句

PrepareStatement可以防止sql注入

预编译语句和Statement不同,创建 PreparedStatement对象时,就指定了sql语句发送到dbms进行编译。当该编译语句被执行时,DBMS直接运行编译后的SQL语句,而不需要像其他SQL语句那样首先将其编译,再执行。


最近更新了一个优化版(工具类中配置了连接池对象连接数据库)   有需要的也可以参考一下:

https://blog.csdn.net/qq_38225558/article/details/82864098

猜你喜欢

转载自blog.csdn.net/qq_38225558/article/details/82843095