JDBC操作之DML
需求:向t_student表中 【插入,修改和删除数据】
步骤1: 加载注册驱动【com.mysql.jdbc.Driver】–》【可以不写,但是习惯问题】
步骤2:获取链接数据库对象Connection --》 DriverManager来获取连接对象
步骤3:编写静态SQL语句–》 【一次性写好SQL并且参数已经确定】—》写成字符串,但是语句中不用分号
步骤4:创建可以执行和发送静态语句的对象Statement --》通过连接对象Connection创建
步骤5:发送语句和执行executeUpdate方法将静态语句进行发送和执行
PS: 这个语句可以执行DDL 和 DML 操作,如果是DML操作会返回一个值,这个值是一个整数,是受影响操作的行数,可以同判断这个数确定是否操作成功【只要大于0即可】
PS: 执行建表语句的时候,返回值是0但是代表建表成功
步骤6:数据库属于长连接,这个资源只要不释放,就会一直保持连接
PS:释放原则:1.程序执行完毕关闭【Demo级别可以】 2.手动释放资源,有一个统一的操作close
插入一条数据到数据库表中
insert into t_student(name,age)values('乔峰',33)
编写代码
package com.qfedu.JDBC.DML;
import java.sql.*;
/**
* 通过JDBC向表中插入数据
*/
public class InsertTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库链接对象
//loaclhost -->代表着两个地址 一个是内环地址【计算自己自带 127.0.0.1】 一个是外环地址【根据网线或路由器分配得来】
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
//3.创建执行和发送静态SQL语句的对象
Statement statement = conn.createStatement();
//4.编写静态SQL语句
String sql = "insert into t_student(name,age)values('乔峰',33)";
//5.执行发送操作
int i = statement.executeUpdate(sql);
if(i > 0) {
System.out.println("插入成功");
}else {
System.out.println("插入失败,执行语句问题");
}
//6.释放资源
statement.close();
conn.close();
}
}
需求:
1. 在插入一条值 啊朱,18
2. 更新数据将乔峰,修改为 萧峰,年龄修改为34
3.将啊朱数据进行删除
package com.qfedu.JDBC.DML;
public class InsertAndUpdateAndDeleteSQL {
private InsertAndUpdateAndDeleteSQL(){};
//提供插入语句【静态SQL】
public static final String INSERT_SQL = "insert into t_student(name,age)values('啊朱',18)";
//提供更新语句
public static final String UPDATE_SQL = "update t_student set name = '萧峰',age = 34 where id = 1";
//删除语句
public static final String DELETE_SQL = "delete from t_student where name = '啊朱'";
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 需求:
*
* 1. 在插入一条值 啊朱,18
* 2. 更新数据将乔峰,修改为 萧峰,年龄修改为34
* 3.将啊朱数据进行删除
*/
public class UpdateAndDelete {
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
/*
JDBC连接驱动路径写法:
1.常规
jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称
2.可以在数据库名称后面添加连接数据
【如果直接和数据库名称相连使用? 剩余的数据库参数使用&符号进行连接】
连接数据库的同时指定数据库的编码集
jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称?useUnicode=true&characterEncoding=UTF-8
3.MySQL 5.6版本开始之后,使用JDBC连接数据库时,数据库连接会对SSL连接进行安全验证
PS:连接数据库的时候回出现一行警告,这个警告不会影响数据库执行
如果出现了这个警告,关闭警告即可
jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称?useSSL=false
ps:习惯性这样书写数据库链接语句
jdbc:mysql://连接数据库服务器的IP地址:3306/连接数据库的名称?useUnicode=true&characterEncoding=UTF-8&useSSL=false
*/
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1", "root", "123456");
Statement statement = connection.createStatement();
//1.执行插入
//InsertTableData(statement);
//2.更新
//atl+ctrl+m --> 快捷抽取方法
//UpdateTableData(statement);
//3.删除
//DeleteTableData(statement);
statement.close();
connection.close();
}
public static void DeleteTableData(Statement statement) throws SQLException {
int i = statement.executeUpdate(InsertAndUpdateAndDeleteSQL.DELETE_SQL);
if (i>0){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
}
public static void UpdateTableData(Statement statement) throws SQLException {
int i = statement.executeUpdate(InsertAndUpdateAndDeleteSQL.UPDATE_SQL);
if (i>0){
System.out.println("更新成功");
}else{
System.out.println("更新失败");
}
}
public static void InsertTableData(Statement statement) throws SQLException {
int i = statement.executeUpdate(InsertAndUpdateAndDeleteSQL.INSERT_SQL);
if (i>0){
System.out.println("插入成功");
}else{
System.out.println("插入失败");
}
}
}
总结:
想通过JDBC对数据库进行增删改操作,就需要使用到一个语句对象Statement【这个对象只接受静态SQL语句】
使用executeUpdate方法进行操作,返回值是一个int类型数据,通过判断这个数据是否大于0即可知道是否添加成功【创建表返回时0,但是操作成功】,DDL和DML都需要和这个方法执行
JDBC操作DQL
DQL语句这里依旧是使用静态SQL语句,还是需要是Statement对象,DQL语句在通过JDBC操作的时候使用方法和得到返回这都有很大改变
返回值类型 | 方法和方法说明 |
---|---|
ResultSet | executeQuery(String sql) 执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。 |
什么ResultSet?
ResultSet表示数据库结果集的数据表,通常通过执行查询数据库的语句【DQL】生成。
通过对对这个虚拟表的操作即可以取出当前虚拟表中的值
PS: 这里大家要记住在学习MySQL时MySQL数据类型对应Java中的数据类型什么
演示代码
package com.qfedu.JDBC.DQL;
import java.sql.*;
/**
* DQL语句通过JDBC进行操作
*/
public class SelectTest {
public static void main(String[] args) throws Exception {
String sql = "select * from t_student";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
Statement statement = connection.createStatement();
//resultSet就是存储这个查询语句得到虚拟表对象
ResultSet resultSet = statement.executeQuery(sql);
System.out.println(resultSet);
//问题:此时返回resultSet确实是一个虚拟表对象com.mysql.jdbc.JDBC4ResultSet@67424e82,所以如何获取其内部值
//在ResultSet官方API中有一句说明,ResultSet存在着一个光标,通过移动这个光标即可以获取到resultSet对象中存值
//ResultSet中提供一个方法 next -->移动光标,如果有下一行数据返回true,否则没有数据则返回false
//利用这个原则,就可以使用while循环,循环获取出结果集中数据了
while(resultSet.next()){//移动光标获取值
//如果需要回去到具体一行数据值,ResultSet提供了两个方法
/*
ps:以下的XXX代表的是不同数据类型,通过get方法表中获取数据的数据类型
1. XXXX getXXXX(int columnIndex)
获取当前光标行的第N列数据【根据表从左向后获取列,左第一列为为1,依次类推】
例如: student表中有三个列 id【1】 name【2】 age【3】
通过当前get方法获取列数据时 getInt(1) --> 相当于获取到 id着列的值
2. XXXX getXXXX(String columnName)
获取当前光标行的列的名字获取列中存储数据
例如: student表中有三个列 id name age
通过当前get方法获取列数据时 getInt(id) --> 相当于获取到 id着列的值
*/
//获取ResultSet对象中存储数据值是一定要注意使用是什么数据类型【☞表中】,接收的时候使用什么数据类型接收【☞Java代码中】
//这两个数据类型一定要一一对应
int id = resultSet.getInt(1);
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
System.out.println("存储在Student表中 ID值是:"+id+" name值是:"+name+" age值是:"+age);
}
//ResultSet也属于长连接对象,所以也要释放
resultSet.close();
statement.close();
connection.close();
}
}
ResultSet执行过程
1.在没有调用next方法之前,光标是在列这一行
2.代用了next方法,光标会移动到一行数据的位置
3.通过getXXX方法获取出这一行数据
4.再次调用next方法,结果没有数据了,返回false 程序结束
需求:统计出t_student中有多少条数据
package com.qfedu.JDBC.DQL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* DQL语句通过JDBC进行操作[统计数据]
*/
public class SelectTest2 {
public static void main(String[] args) throws Exception {
String sql = "select count(id) count from t_student";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
Statement statement = connection.createStatement();
//resultSet就是存储这个查询语句得到虚拟表对象
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()) {
//直接传递列名
int count1 = resultSet.getInt("count");
System.out.println(count1);
//如果要是你确定列个数
int count2 = resultSet.getInt(1);
System.out.println(count2);
}
resultSet.close();
statement.close();
connection.close();
}
}
使用JDBC实现登录案例
1.实现登录
- 创建一张用户表 User
- id ,主键、自动增长。
- 用户名,字符串类型,唯一、非空
- 密码,字符串类型,非空
- 手机号码,字符串类型
- 插入 2 条测试语句
- 通过控制台用户输入用户名和密码。
- 用户输入的用户名和密码作为条件,编写查询 SQL 语句。
- 如果该用户存在,提示登录成功,反之提示失败。
代码
package com.qfedu.JDBC.LogIn;
//提供静态SQL语句
public class CreateAndInsertSQL{
private CreateAndInsertSQL(){};
//提供建表
public static final String CREATE_TABLE =
"create table user(" +
"id int primary key auto_increment," +
"username varchar(20) unique not null," +
"password varchar(20) not null," +
"phoneNumber varchar(20)" +
")";
//提供插入语句
public static final String INSERTINOT_1 =
"insert into user(username,password,phoneNumber)values('zhangsan','123456','13112345678')";
public static final String INSERTINOT_2 =
"insert into user(username,password,phoneNumber)values('lisi','111111','13842383838')";
public static String SelectTableData(String username,String password){
return "select * from user where username = '"+username+"' and password = '"+ password+"'";
}
}
package com.qfedu.JDBC.LogIn;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
//创建表和插入表中数据
public class CreateTableAndInsert{
public static void main(String[] args) throws Exception {
//加载连接驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
//创建执行SQL语句对象【静态语句】
Statement statement = connection.createStatement();
//5.建表
int succeed = statement.executeUpdate(CreateAndInsertSQL.CREATE_TABLE);
if (succeed == 0){
System.out.println("建表成功");
}
int i = statement.executeUpdate(CreateAndInsertSQL.INSERTINOT_1);
int i1 = statement.executeUpdate(CreateAndInsertSQL.INSERTINOT_2);
if(i>0 && i1 >0){
System.out.println("插入数据成功");
}
statement.close();
connection.close();
}
}
package com.qfedu.JDBC.LogIn;
import java.sql.*;
import java.util.Scanner;
public class LoginTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = input.nextLine();
System.out.println("请输入密码:");
String password = input.nextLine();
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(CreateAndInsertSQL.SelectTableData(username, password));
//如果判断是否登录成功
if(resultSet.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
resultSet.close();
statement.close();
connection.close();
}
}
预编译语句对象和JDBC工具抽取封装
预编译语句对象
在之前所有编写MySQL语句的时候,我们都是在开发阶段就要直接将SQL语句写好,并且里面的传输数据也是直接写死,对于这样SQL语句称为【静态SQL语句】,这样静态SQL语句存在一些弊端
【1.不好修改 2.语句中参数是写死的,不能动态获取参数
**3.静态语句没有进行优化 4.静态语句及其容易出现SQL注入】**
Java为了解决这些问题,它提供了一个Statement子类【子接口】,叫做PreparedStatement,它也是一个接口,它提供了一个静态编译语句对象
PreparedStatement表示预编译的 SQL 语句的对象。
SQL 语句被预编译并存储在 PreparedStatement
对象中。然后可以使用此对象多次高效地执行该语句。
在使用预编译语句对象到时候,需要使用到占位符号,进行参数占位 --》 【?】
例如:
静态语句向表中插入数据
insert into t_student(name,age)values('zhangsan',18);
预编译语句性表中插入数据
insert into t_student(name,age)values(?,?);
在语句中【?】只是一个占位符号,没有具体值,所以预编译语句提供一个方法可以对【?】进行赋值操作
void setXXXX(int parameterIndex, XXXX value);
PS:XXX代表传入数据库中数据的数据类型
位置计算,从左向右,占位符的第一位位置是【1】,依次类推
预编译语句和静态语句对比
预编译语句特点:
1.代码的可读性和可维护性比较【因为使用占位,只需要实现一个语句,动态改变值就可以不停查询出不同结果】
ps:所以预编译语句类似于【语句模板】
2.预编译语句可以最大能力提高性能
3.预防SQL注入
SQL语句的执行流程
修改一个案例实现预编译语句
需求:使用预编译语句向t_student插入数据
package com.qfedu.JDBC.PreparedStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
//实现预编译语句
public class PreparedStatementDemo {
public static void main(String[] args)throws Exception {
//1.写预编译语句
String preSQL = "insert into t_student(name,age)values(?,?)";
//加载连接驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
//创建预编译语句对象--》需要传入预编译语句对象进行对象创建
PreparedStatement preparedStatement = connection.prepareStatement(preSQL);
//对象创建完毕之后,语句中还是存在占位符号,所以需要使用预编译语句对象对当前占位符进行赋值
//1.先对预编译语句对象中占位进行赋值
preparedStatement.setString(1,"西方失败");//第一个?赋值
preparedStatement.setInt(2,1);//第二个?赋值
//执行DDL或DML语句,方法依旧是 executeUpdate 这个没有参数直接执行并接收返回值【还是判断是否大于0】
int i = preparedStatement.executeUpdate();
//boolean execute = preparedStatement.execute();
if (i>0){
System.out.println("插入成功");
}else{
System.out.println("插入失败");
}
//预编译语句对象也属于长连接
preparedStatement.close();
connection.close();
}
}
需求:使用预编译语句进行查询
package com.qfedu.JDBC.PreparedStatement;
import jdk.nashorn.internal.ir.CallNode;
import netscape.javascript.JSUtil;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
//实现预编译语句
public class PreparedStatementDemo2 {
public static void main(String[] args)throws Exception {
//1.写预编译语句
String preSQL = "select * from t_student where id = ?";
//加载连接驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1","root","123456");
//创建预编译语句对象--》需要传入预编译语句对象进行对象创建
PreparedStatement preparedStatement = connection.prepareStatement(preSQL);
//对象创建完毕之后,语句中还是存在占位符号,所以需要使用预编译语句对象对当前占位符进行赋值
//1.先对预编译语句对象中占位进行赋值
preparedStatement.setInt(1,4);
//2.使用DQL语言进行查询 executeQuery方法,这个方法没有参数
ResultSet resultSet = preparedStatement.executeQuery();
boolean execute = preparedStatement.execute();
System.out.println(execute);
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
System.out.println(id+name+age);
}
//预编译语句对象也属于长连接
preparedStatement.close();
connection.close();
}
}
ps:预编译语句中提供一个execute方法,这个方法返回值是boolean,即可以运行DDL和DML,也可以运行DQL,但是这个方法的返回值决定点在于是否可以获取到一个ResultSet对象,也就是说execute方法对查询语句的到ResultSet结果集之后会返回【true】,剩余DDL和DML返回值为【false】
综上所述:
1.对于预编译语句而言,可以依旧使用executeUpdate执行【DDL和DML】语句,也可以使用executeQuery执行【DQL】语句,这两个方法对比静态语句中方法少了方法形参,但是执行效果是一样的
模拟SQL注入
package com.qfedu.JDBC.PreparedStatement;
import java.sql.*;
/**
* SQL注入操作
*/
public class LoginTest {
public static void main(String[] args) throws Exception {
//用户注册信息user表,只有用户名和密码正取之后才能让其登录
//1.静态SQL语句
String staticSQL = "select * from user where username = '' OR 1 = 1 AND password = '123456'";
String perSQL = "select * from user where username = ? AND password = ?";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1", "root", "123456");
// Statement statement = connection.createStatement();
// ResultSet resultSet = statement.executeQuery(staticSQL);
// if(resultSet.next()){
// System.out.println("登录成功");
// }else{
// System.out.println("登录失败");
// }
PreparedStatement preparedStatement = connection.prepareStatement(perSQL);
//因为数据是以占位符的形式传递进去
//因为预编译语句会将参数看做是一个字段【列】一个值 而不是当做一个SQL语句运行
/*
说明:
静态SQL中,它会将where子句的后面看做时一个表达式 和整个整个语句融为一体,是一个完整的SQL
预编译语句,他会将出现占位符号的位置,看做就是一个字段【列】的值
ps:将 '' OR 1 = 1 看做是一个用户名即 username列里面是否存在和这个值
*/
preparedStatement.setString(1,"'' OR 1 = 1");
}
}
核心:"为了SQL语句的安全建议开发的时候都写预编译语句"
JDBC封装工具类
在实际开发JDBC的过程中,存在大量向同的重复性代码【触发了DRY原则】,所以我们需要对重复的代码进行抽取,封装到一个统一的类中,通过这类就可以获取到JDBC的基础操作,就不用大量重复编写代码
通过对之前代码的简单分析可以的到一些结论
1.加载注册驱动每个对象都需要使用
2.获取连接对象
在获取连接对象的时候用,需要传递参数,如果将参数写死在代码中,如果修改连接数据库,那么你就要查找对应代码才能修改,还是需要修改原码,所以建议将当前数据封装到一个文件中,读取这个文件即可以获取到链接的数据,以后要修改连接的时候,无需查找代码,只需要文件即可
- 数据库的连接属于一个【长连接】,程序不关闭的且没有做任何资源释放,后果就是一直会有一个连接资源占用,如果是Demo级别,其实没有大问题,但是在实际开发中10万人连接,服务器的内存压力就非常大,甚至会出现崩溃【宕机】
抽取一个工具类【DBUtil】这个工具类中就提供以上三种操作,后续需要什么在向这个类添加即可
步骤1:创建一个资源文件,将会数据库连接参数写入到文件中,使用时读取文件即可
#数据库连接配置写到这个文件中
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb1
username=root
password=123456
步骤2:抽取创建DBUtil工具类
package com.qfedu.JDBC.util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* JDBC工具类
*/
public class DBUtil {
//1.工具类不会创建对象,所以将构造方法私有化
private DBUtil(){}
//2.创建一个Properties文件对象以便读取文件中的数据
private static final Properties p = new Properties();
//3.提供一个静态代码块 用来对要使用数据库连接对象进行配置
static {
//3.1先文件中内容读取出来
try {
//获取类的类的加载器
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//通过类的加载器获取classPath路径下文件【db.properties】
InputStream resourceAsStream = contextClassLoader.getResourceAsStream("db.properties");
p.load(resourceAsStream);//通过字节流加载
} catch (IOException e) {
throw new RuntimeException("加载classPath路径下的db.properties文件出现失败:"+e.getMessage());
}
//3.2 加载注册驱动
try {
Class.forName(p.getProperty("driver"));
} catch (ClassNotFoundException e) {
throw new RuntimeException("数据库驱动加载失败:"+e.getMessage());
}
}
/**
* 获取Connection连接对象
* @return Connection连接对象
* 会抛出异常,连接对象获取失败
*/
public static Connection getConnectionInstance(){
try {
return DriverManager.getConnection(p.getProperty("url"),p.getProperty("username"),p.getProperty("password"));
} catch (SQLException e) {
throw new RuntimeException("数据库获取连接对象失败:"+e.getMessage());
}
}
/**
* 释放JDBC连接资源对象
* @param connection 连接对象
* @param statement 静态SQL语句对象
* @param preparedStatement 预编译语句对象
* @param resultSet 结果集
*/
public static void closeAll(Connection connection, Statement statement, PreparedStatement preparedStatement, ResultSet resultSet){
//这里的释放原则,只要创建就是释放 反之不执行
try {
if (connection != null) {
connection.close();
}
if (statement != null) {
statement.close();
}
if(preparedStatement != null){
preparedStatement.close();
}
if(resultSet != null){
resultSet.close();
}
}catch (SQLException e){
throw new RuntimeException("释放资源出出现失败:"+e.getMessage());
}
}
}
步骤3:测试工具类
package com.qfedu.JDBC.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBTest {
public static void main(String[] args) throws SQLException {
//查询语句
String sql = "select * from t_student where id = ?";
//1.加载驱动获取连接对象
Connection connection = DBUtil.getConnectionInstance();
//2.获取预编译语句对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,3);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
System.out.println("查询成功");
}
DBUtil.closeAll(connection,null,preparedStatement,resultSet);
}
}
JDBC之ORM映射
ORM(object Relational Mapping)从数据库中查询出的结果集(ResultSet)在进行遍历是,我们逐行取出值,但是这个是零散,所以为了使用方便,在实际开发中提供了一种思想,更加便于管理这些零散数据,主要是提供了对零散数据的封装,提供公益的访问方式和使用途径
PS:关系型数据库和Java中的类是存在一定联系
数据库中表 -----》 看做 -----》Java中类
数据库中表的列 ----》 看做 ----》 Java中类中属性
数据库中表的每一行数据 —》 看做 —》 java中类的对象
所以就是因为存在这种关系 —》称之为 【ORM映射】
因为要将这些零散进行封装,所以就需要提供一个存储零散数据载题,这个载体就叫做**【实体类】**
ps:什么是实体类?就是刚开始学习面向对象时的描述类
什么是实体类(entity)?
实体类的作用就是通过ResultSet查询出来的零散数据的统一载体
一行数据中,多个零散的数据进行整体的封装,通过entity的规则对表中数据进行对象的封装
实体类的设计原则?
【表名 == 类型】 【列 == 属性】 【实体类要提供get和set方法】 【提供有参无参构造方法】
扩展: JavaBean规范
ps:实体类就是JavaBean
JavaBean是一种Java语言的一个重要的组件【就是一个类】
要写和这个JavaBean这类就需要遵守一个规范
1.这个类必须使用public修饰
2.必须保证有【有参无参构造反方】
3.包含处理属性操作的手段【提供get和set】
JavaBean规范类一般多用于domain、dao、services组件中分装类【存储数据使用】
实例类案例
package com.qfedu.JDBC.entity;
//这类就是tbStock这个表的实体类
public class T_tbStock {
//跟表中列的名一致【属性名】
private String ordername;
private String locationid;
private String dateid;
//这类提供get和Set 还有有参无参构造方法
public T_tbStock() {
}
public T_tbStock(String ordername, String locationid, String dateid) {
this.ordername = ordername;
this.locationid = locationid;
this.dateid = dateid;
}
public String getOrdername() {
return ordername;
}
public void setOrdername(String ordername) {
this.ordername = ordername;
}
public String getLocationid() {
return locationid;
}
public void setLocationid(String locationid) {
this.locationid = locationid;
}
public String getDateid() {
return dateid;
}
public void setDateid(String dateid) {
this.dateid = dateid;
}
@Override
public String toString() {
return "T_tbStock{" +
"ordername='" + ordername + '\'' +
", locationid='" + locationid + '\'' +
", dateid='" + dateid + '\'' +
'}';
}
}
package com.qfedu.JDBC.entity;
import com.qfedu.JDBC.util.DBUtil;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/*
实体类使用
*/
public class T_tbStockTest {
public static void main(String[] args) throws Exception {
//1.需要加载注册驱动和创建连接对象
Connection connection = DBUtil.getConnectionInstance();
String sql = "select * from tbstock";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
//如果按照以前的方式
// while(resultSet.next()){
// //零散数据的体现其实就是这个表中值,我们无法提供合理方式进行存
// String ordername = resultSet.getString(1);
// String locationid = resultSet.getString(2);
// String dateid = resultSet.getString(3);
// }
//以表和类之间产生一个映射关系【ORM】 表即是类 表中列即是类中属性 表中每一行数据封装在这个类的对象
List<T_tbStock> list = new ArrayList<>();
while(resultSet.next()){
String ordername = resultSet.getString(1);
String locationid = resultSet.getString(2);
String dateid = resultSet.getString(3);
//将数据分装进对象中
T_tbStock tb = new T_tbStock(ordername,locationid,dateid);
list.add(tb);
}
list.forEach(System.out::println);
}
}
DAO数据访问对象(Data Access Object)
什么DAO:主要作用就是执行【CRUD(增删改查)】
DAO是一个数据访问接口,数据访问:顾名思义就是与数据库打交道
在核心JavaEE中是这样介绍DAO模式的:为了建立一个健壮的JavaEE的应用程序,应该将所有对数据库的访问抽象的封装在一个公共API中
用程序设计的语言来说,其实就是建议一个接口,接口中定了此应用程序中将会用到所有事务方法
在应用程序中,当需要和数据源进行交互的时候,则直接使用这个接口,并编写一个实现接口类,这个类中将实现接口所有的方法,并且对外提供暴露,外部只需要调用这个类就可以完成对数据库的操作,这个操作就是DAO包中核心
扩展 :DAO包中设计方式
DAO包的设计规范:
DAO包中组件:【DAO接口、DAO实现类、DAO的测试类】
分包的规范:
【以下仅以我开发经验而言】
com.公司的域名.项目名称.dao --> 存储着dao包中接口文件
com.公司的域名.项目名称.dao.impl --> 存储着Dao包中接口的实现类
com.公司的域名.项目名称.dao.domian --> 存放着Dao包中需要使用到实体类【ORM思想】
PS:有的的地方习惯将实体类单独抽取出来一个包entity,含义和domian是一样的
com.公司的域名.项目名称.dao.test --> 存测试文件
PS:在实际项目提交【甲方爸爸】,需要将test全员删除
JavaSE是以jar为打包,可以提供对外使用
JavaEE是以war为打包,可以提供对外使用
具体包所创建的东西
domain包:描述对象的,一般就是存储实体类 例如:Person.java
dao包: 接口文件【定义操作数据库的方法CRUD】 例如: IPersonDao 或 IPersonDAO
impl包: 这个包就是对dao中接口的具体实现类【CRUD】 例如:IPersonDAOImpl
test包: 测试包对impl包中实现类测试是否可以使用,能否争取完成操作 例如:PersonDAOTest
创建DAO包之后,我们需要使用面向接口编程:
所有触发DAO包的操作都需要使用接口来实现对象创建
例如: IPersonDAO pd = new IPersonDAOImpl();