英语渣渣学Java的day6

2 篇文章 0 订阅

java练习题

1.查询员工名、部门名和所在的城市 employees,departments,locations

SELECT 
  e.first_name 员工名,
  d.department_name 部门名,
  l.city 城市
FROM
  employees e,
  departments d,
  locations l 
WHERE e.`department_id` = d.`department_id` 
  AND l.`location_id` = d.`location_id` ;

效果图:
在这里插入图片描述

2.利用JDBC创建下面的表格

学生表(student)
字段 名称 数据类型 约束
学号 S_NO INT(8) 主键
姓名 S_NAME VARCHAR(10)
性别 S_SEX VARCHAR(2)
入学成绩 S_SCORE DOUBLE
附加分 S_ADDF DOUBLE

package com.gec.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import java.sql.Statement;

public class DDLDemo {
	public static void main(String[] args) throws SQLException {
		//加载驱动
		 try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//获得连接
		Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/shanping","root","");
		//获得语句对象
		Statement st =  conn.createStatement();
		//执行语句
		String sql = "CREATE TABLE student(S_NO INT(8) PRIMARY KEY AUTO_INCREMENT"
				+ ",S_NAME VARCHAR(10)"
				+ ",S_SEX VARCHAR(2)"
				+ ",S_SCORE DOUBLE"
				+ ",S_ADDF DOUBLE)";
		st.executeUpdate(sql);
		
		System.out.println("创建成功...");
		//释放资源
		st.close();
		conn.close();
		
	}

}


效果图:
在这里插入图片描述

关闭资源

使用连接工具管理连接
在工程中,通常编写一个访问数据库的工具类,此后所有访问数据库的操作,都使用工具类获取连接和关闭连接。这样做的好处是统一使用共同工具类来管理连接,简化连接操作。

繁琐的关闭资源的方法

package com.gec.close;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class CloseResourceDemo {
	public static void main(String[] args) {
		//注册驱动
		try {
			//mysql com.mysql.cj.jdbc.Driver
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		//利用驱动管理获得连接 
		Connection conn =  null;
		Statement st = null;
		try {
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/g2148", "root", "root");
			System.out.println("conn:" + conn);
			
			st = conn.createStatement();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//关闭连接 
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}finally {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
}

注意:要关闭的对象越多就要用到更多的try{};

简单的关闭资源

package com.gec.close;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class JDK7CloseDemo2 {
	public static void main(String[] args) {
		//注册驱动
		try {
			//mysql com.mysql.cj.jdbc.Driver
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		//利用驱动管理获得连接 
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/g2148", "root", "root");
			Statement st = conn.createStatement();
			){
			
			System.out.println("conn:" + conn);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

注意:try(拥有自带关闭资源){}

ResultSet接口

执行查询SQL语句后返回的结果集,由ResultSet接口接收。

常用处理方式:遍历 / 判断是否有结果。

ResultSet对象表示数据库查询操作的结果集。访问该结果集数据需要通过光标操作。最初,光标位于第一行之前,需要调用next方法将光标移到下一行,如果在ResultSet对象上没有下一行,该方法返回false,一般可以与while循环一起使用来遍历结果集ResultSet提供了getXXX(String column)的方法来获取当前ResultSet对象当期行中指定的列的值,其中xxx是类型,与数据库列值的类型一致,column是数据库中表的列名

释放资源
数据库的连接是有限资源,相关操作结束后,养成关闭数据库的好习惯。

在finally块中依次关闭ResultSet对象、Statement对象和Connection对象

package com.gec.dql3;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class SingleQuery {
	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver");
		
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");	
			Statement st = conn.createStatement();	
			ResultSet rs = st.executeQuery("select * from t_user where id = 2");
			){
			//返回结果集 遍历 
			while(rs.next()) {
				//获取列值
				/*
				 Object id = rs.getObject(1);//传的是列的索引,如果表的列过多,这将容易数错了 2)Object的数据还得强转,不方便
				 Object name = rs.getObject(2);
				 Object password = rs.getObject(3);
				 */
				int id = rs.getInt(1);
				String name = rs.getString("name");
				String password = rs.getString("password");
				System.out.println(id + ":" + name + ":" + password);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

PreparedStatement

概述
Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句。Statement每执行一次都要对传入的SQL语句编译一次,效率较差。

某些情况下,SQL语句只是其中的参数有所不同,其余子句完全相同,适合使用PreparedStatement

PreparedStatement的另外一个重要好处就是预防sql注入攻击。

PreparedStatement接口
PreparedStatement接口继承自Statement接口,使用PreparedStatement时,SQL语句已提前编译,三种常用方法 execute、 executeQuery 和 executeUpdate 已被更改,以使之不再需要参数。

PreparedStatement 实例包含已事先编译的SQL语句,SQL语句可有一个或多个参数,参数的值在 SQL语句创建时未被指定。该语句为每个参数保留一个问号(“?”)作为占位符
每个问号的值必须在该语句执行之前,通过适当的setInt或者setString 等方法提供。
由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。
PreparedStatement实现更新操作
示例,在StuDao添加更新方法,通过PreparedStatement接口实现更新emp数据

使用PreparedStatement来执行SQL语句。在SQL语句中有2个问号,在代码中要给它们分别设置值,规则是:从左到右,对应1,2,…。

通过PreparedStatement提升性能
一个sql语句执行过程中,将经历这么几个步骤:

传输SQL给数据库
数据库验证并解析SQL
计算执行计划(Access Plan),数据库会制定出最优的访问计划。
根据访问计划进行检索,返回数据。
案例

package com.gec.preparestatement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

public class PrepareStatementLogin2 {
	public static void main(String[] args) {
		String name = "xx";
		//String password = "123";
		
		String password = "' or '1'='1";//恒等式  1=1 2=2 3=3
		//String sql = "select * from t_user where name = '" + name + "' and password = '" + password + "'";
		
		
		String sql = "select * from t_user where name = ? and password = ?";
		
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");
			PreparedStatement st = conn.prepareStatement(sql);
			) {
			//给问号设置值
			st.setString(1, name);
			st.setString(2, password);
			
			//查询时不需要带参数
			ResultSet rs = st.executeQuery();
			//statement : sql:select * from t_user where name = 'xx' and password = '' or '1'='1'
			//prestatement:   select * from t_user where name = 'xx' and password = '\' or \'1\'=\'1'
			System.out.println("sql:" + st);
			while(rs.next()) {
				System.out.println(rs.getInt("id") + ":" + rs.getString("name") + ":" + rs.getString("password"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
			
	}
}

用jdbc做一个简单的增删改

package com.gec.preparestatement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

import org.junit.Test;

public class CUDDemo3 {
	
	@Test
	public void testAdd() {
		String sql = "insert into t_user(name,password)values(?,?)";
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");
			PreparedStatement st = conn.prepareStatement(sql);
			){
			//给问号设置值
			st.setString(1, "tom");
			st.setString(2, "222");
			
			//执行语句 
			st.executeUpdate();//不要传sql进来 
			
			System.out.println("添加成功...");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testUpdate() {
		String sql = "update t_user set name = ?,password=? where id = ?";
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");
			PreparedStatement st = conn.prepareStatement(sql);
			){
			//给问号设置值
			st.setString(1, "tom 张");
			st.setString(2, "888");
			st.setInt(3, 3);
			
			//执行语句 
			st.executeUpdate();//不要传sql进来 
			
			//打印sql
			System.out.println(st);
			
			System.out.println("修改成功...");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testDel() {
		String sql = "delete from t_user where id = ?";
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm","root", "root");
			PreparedStatement st = conn.prepareStatement(sql);
			){
			//给问号设置值
			st.setInt(1, 2);
			//执行语句 
			st.executeUpdate();// 执行ddl dml 
			
			//执行打印的sql
			System.out.println("sql:" + st);
			
			System.out.println("删除成功....");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

我们一直用class.forname() ,这句代码是为了加载驱动。其实jdbc4.0以后我们不需要再写这块代码。DriverManage已经增加自动加载驱动包的功能。当然前提是你的工程有相关的数据库驱动包。。DM会去jar包的meta-inf/services寻找文件该文件记录了驱动信息。

DAO

Data Access Object:数据访问对象
直白理解:Dao对某一个表的增删改查封装起来的一个类

程序对dao接口是感知不到操作数据库的存在,隔离开来的
Dao接口:UserDao
Void save(User user);
Void update(User user);
Void delete(int id);
User getUserById(int id);
List findUsers();
Dao接口的实现类:UserDaoImpl impl:implements
具体操作数据库的类
实现类可能是操作mysql/oracle
高内聚,低耦合(文件解耦)

案例
封装

package com.gec.dao.impl;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.gec.bean.User;
import com.gec.dao.UserDao;

public class UserDaoImpl implements UserDao {

	@Override
	public void save(User user) {
		String sql = "insert into t_user(name,password)values(?,?)";
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");
			PreparedStatement st = conn.prepareStatement(sql);
			){
			//给问号设置值
			st.setString(1, user.getName());
			st.setString(2, user.getPassword());
			
			//执行语句 
			st.executeUpdate();//不要传sql进来 
			
			System.out.println("执行的sql:" + st);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public void update(User user) {
		String sql = "update t_user set name = ?,password=? where id = ?";
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");
			PreparedStatement st = conn.prepareStatement(sql);
			){
			//给问号设置值
			st.setString(1, user.getName());
			st.setString(2, user.getPassword());
			st.setInt(3, user.getId());
			
			//执行语句 
			st.executeUpdate();//不要传sql进来 
			
			//打印sql
			System.out.println("执行的sql:" + st);
			
			System.out.println("修改成功...");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void delete(User user) {
		String sql = "delete from t_user where id = ?";
		try(
			Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm","root", "root");
			PreparedStatement st = conn.prepareStatement(sql);
			){
			//给问号设置值
			st.setInt(1, user.getId());
			//执行语句 
			st.executeUpdate();// 执行ddl dml 
			
			//执行打印的sql
			System.out.println("sql:" + st);
			
			System.out.println("删除成功....");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public User getUserById(int id) {
		String sql = "select * from t_user where id = ?";
		try(
				Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");	
				PreparedStatement st = conn.prepareStatement(sql);
				
				){
				st.setInt(1, id);
				ResultSet rs = st.executeQuery();
				System.out.println("执行的sql:" + st);
				//返回结果集 遍历 
				while(rs.next()) {
					//创建用户对象
					User user = new User();
					int uid = rs.getInt(1);
					String name = rs.getString("name");
					String password = rs.getString("password");
					
					user.setId(uid);
					user.setName(name);
					user.setPassword(password);
					
					//返回用户信息
					return user;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		return null;
	}

	@Override
	public List<User> findUsers() {
		//定义集合
		List<User> users = new ArrayList<>();
		try(
				Connection conn = DriverManager.getConnection("jdbc:mysql:///hrm", "root", "root");	
				PreparedStatement st = conn.prepareStatement("select * from t_user");	
				ResultSet rs = st.executeQuery();
				){
				//返回结果集 遍历 
				while(rs.next()) {
					//创建用户对象
					User user = new User();
					int uid = rs.getInt(1);
					String name = rs.getString("name");
					String password = rs.getString("password");
					
					user.setId(uid);
					user.setName(name);
					user.setPassword(password);
					//每个用户放到集合里面
					users.add(user);
				}
				
				return users;
			} catch (Exception e) {
				e.printStackTrace();
			}
		return null;
	}

}

调用

package com.gec.dao;

import java.util.List;

import com.gec.bean.User;

/*
 * 增删改查方法
 * dao:data access object
 */
public interface UserDao {
	
	/** alt+shift+j 快速生成注释
	 * @param user
	 */
	void save(User user);
	
	/**修改用户信息
	 * @param user
	 */
	void update(User user);
	
	/**删除用户信息
	 * @param user
	 */
	void delete(User user);
	
	/**根据id查找用户
	 * @param id
	 * @return
	 */
	User getUserById(int id);
	
	/**查找所有用户
	 * @return
	 */
	List<User> findUsers();
}

package com.gec.bean;

public class User {
	private int id;
	private String name;
	private String password;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", password=" + password + "]";
	}
	public User(int id, String name, String password) {
		super();
		this.id = id;
		this.name = name;
		this.password = password;
	}
	public User() {
		super();
	}
	
}

优化封装我就不写了,我自己都看不懂
参考:
https://blog.csdn.net/qq_36962829/article/details/79035067

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

沉莫的羔羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值