千峰JAVA逆战班Day39

Day39

*java制定了一套统一的接口来连接不同的数据库,各大数据库厂商按照这个接口实现了连接各自数据库的方案(如下图):

在这里插入图片描述

*使用JDBC执行DQL语句,并将结果保存在一个集合里面
public class TestJDBCtoList {

	public static void main(String[] args) {
		Connection con = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://127.0.0.1:3306/nz2001";
			String name = "root";
			String pass = "123";
			con = DriverManager.getConnection(url, name, pass);

			String sql = "SELECT uid id,uname,upass FROM USER";
			ps = con.prepareStatement(sql);
			//·使用executeQuery方法执行DQL语句并得到一个结果集:ResultSet
			rs = ps.executeQuery();
			
			List<User> user = new ArrayList<User>();
			//·next方法:判断有没有下一行,如果有则返回true,并且指针指向下一行(第一次的时候指针指向的是表头)
			//·表头指的就是显示别名的那一行
			while(rs.next()) {
				//·get方法里面的字符串都是别名 而不是字段名
				User u = new User(rs.getInt("id"), rs.getString("uname"), rs.getString("upass"));
				user.add(u);
			}
			//·遍历打印
			for (User u : user) {
				System.out.println(u);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
            //·关闭
			try {
				if(null != rs) {
					rs.close();
				}
				if(null != ps) {
					ps.close();
				}
				if(null != con) {
					con.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

public class User {
	private int uid;
	private String uname;
	private String upass;
    //user实体类,构造方法,getset方法,tostring方法略
}
*使用DQL语句进行登录逻辑:(对上面进行更改)

​ I. 首先需要更改sql语句,这里也可以将全部记录查询到再筛选,但是效率很低而且代码过于繁琐。

String sql = "select uid,uname,upass from user where uname=? and upass=?";

​ II. 添加上控制台录入

Scanner input = new Scanner(System.in);
System.out.println("请输入用户名");
String username = input.nextLine();
System.out.println("请输入密码");
String password = input.nextLine();
input.close();

​ III. 修改预处理语句,将控制台接受到的用户名和密码加入到sql语句中

ps.setString(1, username);
ps.setString(2, password);

​ IV. 使用if语句判断是否得到查询结果(因为不会有两条用户名和密码一模一样的数据,这里的查询结果只有两种情况:查到结果和没查到结果)

if (rs.next()) {
	System.out.println("登录成功");
} else {
	System.out.println("登录失败");
}
*批处理(需要做批处理操作时,url需要加上?rewriteBatchedStatements=true,才是真正的批处理。MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL)

​ I. 对不同的sql进行批处理

​ 1)写几个不同的DML语句

String sql1 = "INSERT INTO USER(uname,upass) VALUES('zhangsan',777)";
String sql2 = "UPDATE USER SET upass=789 WHERE uname='tom'";
String sql3 = "DELETE FROM USER WHERE uid=1";

​ 2)执行并清空批处理

//·执行批处理,每一条sql语句返回一个int值(数据库受影响行数),并保存在一个int数组中然后返回
int[] result = st.executeBatch();//·打印这个result数组的结果是1  1  1
st.clearBatch();//·清空批处理

在这里插入图片描述

​ II. 对相同的sql进行批处理

​ 1)写一个带有占位符的sql语句

String sql = "insert into user(uname,upass) values(?,?)";

​ 2)使用循环进行预处理,然后添加进批处理中

for (int i = 0; i < 100; i++) {
	ps.setString(1, "jack"+i);
	ps.setString(2, "pass"+i);
	ps.addBatch();
}

​ 3)执行并清空

ps.executeBatch();
ps.clearBatch();

在这里插入图片描述

*DBUtils封装(每次使用JDBC连接数据库时,都会产生大量的重复代码,所以对连接数据库的一些必要操作进行封装)

​ I. 因为加载驱动只需要进行一次,所以写在静态代码块中;由于是工具类,属性都是静态的,所以可以在静态代码块中对静态属性进行初始化。将三个字符串(url,user,password)信息封装到jdbc.properties,并将编译后的文件添加至编译后文件夹(bin文件夹)的根目录。

在这里插入图片描述

/*
* ·DBUtil.class.getClassLoader()得到一个类加载器对象
* ·可以理解为bin下面的文件都归这个类加载器管理,
* ·再用getResourceAsStream方法获得一个对jdbc.properties文件的输入流
*/
InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties p = new Properties();
p.load(is);
			
url = p.getProperty("url");
user = p.getProperty("user");
pass = p.getProperty("pass");
//·加载驱动
Class.forName("com.mysql.jdbc.Driver");

​ II. 获取连接

public static Connection getConnection() {
	try {
		return DriverManager.getConnection(url, user, pass);
	} catch (SQLException e) {
		e.printStackTrace();
	}
	return null;
}

​ III. 关闭连接

	public static void close(Connection con, PreparedStatement ps, ResultSet rs) {
		closeRs(rs);
		closePs(ps);
		closeCon(con);
	}

	private static void closeRs(ResultSet rs) {
		if(null != rs) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	private static void closePs(PreparedStatement ps) {
		if(null != ps) {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	private static void closeCon(Connection con) {
		if(null != con) {
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
*对统一的DML语句进行封装:使用object的可变长参数(多态的应用)
public static boolean executeDML(String sql,Object... params) throws SQLException {
	//·使用封装好的工具类获取连接
	Connection con = DBUtil.getConnection();
	//·获取预处理对象
	PreparedStatement ps = con.prepareStatement(sql);
	//·设置参数
	setParams(ps,params);
	//·大于0则表示执行成功
	return ps.executeUpdate() > 0;
}
private static void setParams(PreparedStatement ps, Object... params) throws SQLException {
	if(params != null) {
		for (int i = 0; i < params.length; i++) {
			//·对ps对象进行循环设置参数
			ps.setObject(i, params[i]);
		}
	}
}
*补充知识:查询表的元数据(有哪些列,列名,一共有多少列 等等)
	public static void main(String[] args) throws SQLException {
		Connection con = DBUtil.getConnection();
		String sql = "SELECT pid,pname,page FROM person";
		PreparedStatement ps = con.prepareStatement(sql);
		
		//·获取表的元数据对象,里面封装了表的所有元数据
		ResultSetMetaData rm = ps.getMetaData();
		//·getColumnCount获取列的个数
		for (int i = 0; i < rm.getColumnCount(); i++) {
			System.out.println("列名:"+rm.getColumnName(i+1)+",别名:"+rm.getColumnLabel(i+1)
			+",数据库中的类型:"+rm.getColumnTypeName(i+1)+",java中的类型 "+rm.getColumnClassName(i+1));
		}
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值