JDBC

JDBC介绍JDBC

(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库。原来我们操作数据库是在控制台使用SQL语句来操作数据库,JDBC是用Java语言向数据库发送SQL语句。

JDBC中的核心类有

●DriverManager(驱动管理器)的作用有两个:

1)注册驱动:这可以让JDBC知道要使用的是哪个驱动;
2)获取Connection:如果可以获取到Connection,那么说明已经与数据库连接上了。

Connection对象表示连接

与数据库的通讯都是通过这个对象展开的:它最为重要的一个方法就是用来获取Statement对象;

 ●Statement

是用来向数据库发送SQL语句的,这样数据库就会执行发送过来的SQL语句:

1)int executeUpdate(String sql):执行更新操作(insert、update、delete等);
2)ResultSet executeQuery(String sql):执行查询操作,数据库在执行查询后会把查询结果,查询结果就是ResultSet;
ResultSet

对象表示查询结果集,只有在执行查询操作后才会有结果集的产生。结果集是一个二维的表格,有行有列。操作结果集要学习移动ResultSet内部的“行光标”,以及获取当前行上的每一列上的数据:

boolean next():使“行光标”移动到下一行,并返回移动后的行是否存在;

XXX getXXX(int col):获取当前行指定列上的值,参数就是列数,列数从1开始,而不是0。

mysql数据库的驱动jar包

mysql-connector-java-5.1.13-bin.jar;

JDBC访问数据库的步骤

加载驱动 【DriverManager】

1. JDBC实际上就是定义了一系列的接口和类,集成在java.sql和javas.sql包中
2. 需要使用不同厂商提供的DriverManager来管理jdbc驱动
3. 不同的驱动是用来连接不同类型的数据库的

操作
    1.添加jar包到项目中
    2.使用反射原理来获取驱动
        Class.forName("com.mysql.jdbc.Driver");//反射
获取Connection链接

1.使用刚刚加载好的驱动来获取管理驱动

2. 获取的俩接种有三各参数需要注意

1.url
    jdbc:mysql://localhost:3306/colin_mysql【咱们自己要连接的数据库的名字】
    jdbc:mysql:///colin_mysql
2. user
    root
3. password
    1234

操作:

//根据DrivateManager来调用获取链接的方法       
String url = "jdbc:mysql://localhost:3306/colinemp";
     url是我们数据库的地址  最后使我们要连接的数据库名

String user = "root";
String password = "1234";

Connection con = DriverManager.getConnection(url, user, password);

创建Statement  ['steɪtm(ə)nt] 执行SQL语句

1. 根据刚刚创建的连接,生成一个执行sql 语句的状态对象

2. 准备好sql语句

1.增 insert
2. 删 delete
3. 改 update
使用的是executeUpdate  ['eksɪkjuːt] (sql语句) 来执行的sql语句的。
返回的是一个int值【也就是这条sql语句执行后影响的数据条数
(有数据条数被影响那就说明成功,没有被影响的话那就说明失败)】

4.查询 select
使用的是executeQuery   ['kwɪri](sql语句 ) 来执行的查询的sql语句。
返回的是一个ResultSet结果集。我们需要遍历来获取数据库的信息   
循环判断结果集还是否存在下一条数据【如果存在就将数据库中的数据使用结果集对象来获取通过列名
(需要注意的是在关闭数据库释放资源的时候也要把结果集关闭掉)】

操作:

增删改
//
statement对象用来发送sql语句 他是根据连接对象来生成的一个状态 stt = con.createStatement();//打开状态通道 String sql ="insert into dept values(50,'后勤部','天津')"; 准备一个sal语句【增删改】 //调用方法来处理语句 int i = stt.executeUpdate(sql); 逻辑判断 if(i>0){ System.out.println("添加成功"); }else{ System.out.println("添加失败"); }

查询

//statement对象用来发送sql语句 他是根据连接对象来生成的一个状态
stt = con.createStatement();
String sql = "select * from dept";
准备sql语句
// 只有在进行查询的时候我们使用的是executeQuery()
rs = stt.executeQuery(sql);
//遍历结果集 获取信息
while(rs.next()){//判断是否存在下一条数据
int id = rs.getInt("deptno");//可以写列的名字 也可以写列的下标 1
String name = rs.getString("deptname");//下标是 2
System.out.println(id+" --- "+name);
}



4. 返回ResultSet 查询结果

1.只有在查询的时候才会用到。
2. 需要通过遍历结果集来获取数据库中相应的信息

5. 关闭数据库,释放资源

1. 在关闭之前首要要做的是否空判断。
2. 在做查询时注意也需要将结果集进行关闭。

操作:

增删改
//释放资源
try {
    if(stt != null){
    stt.close();
    }
    if(con != null){
    con.close();
    }
} catch (SQLException e) {
e.printStackTrace();
}


查询
//释放资源
try {
    if(rs!= null){
    rs.close();
    }
    if(stt != null){
    stt.close();
    }
    if(con != null){
    con.close();
    }
    需要注意的是 rs结果集也是需要我们进行一个关闭操作的
} catch (SQLException e) {
e.printStackTrace();
}

sql注入

关于sql语句中信息显示是否安全

如果我们从控制台输入信息 直接放入了sql语句中,是一种非常不安全的行为

当我们使用变量拼接sql语句的时候,会出现一种情况

 直接修改sql语句 【手动拼接sql语句 改变了sql语句原来的逻辑顺序【语意】】完成了一个不需要正确密码和用户名的正确登陆得到数据信息

例如:

 select * from Student where s_id="1" or 1=1 and s_sex="男" or 1=1;
这种就是直接篡改的语义,从而跳过数据库的验证,直接进行操作的方法

预编译PreparedStatement

它是Statement接口的子接口;

强大之处:
●防SQL攻击;
●提高代码的可读性、可维护性;
●提高效率
使用
1.使用Connection的prepareStatement(String sql):即创建它时就让它与一条SQL模板绑定;
    select * from user where name = ? and pass = ?;
        sql语句模板【?就是占位符】
2.调用PreparedStatement的setXXX()系列方法为问号设置值

3.调用executeUpdate()或executeQuery()方法,但要注意,调用没有参数的方法; 建议大家在今后的开发中,无论什么情况,都去需要PreparedStatement,而不是使用Statement。
代码示例
//1.加载驱动
    Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
    String url ="jdbc:mysql://localhost:3306/colinemp";
    String user ="root";
    String password = "1234";
    con = DriverManager.getConnection(url, user, password);
//3.开启通道发送sql语句
    String sql = "select * from user where name =? and pass = ? ";
        sql语句模板
            问号是占位符的意思
    pstt = con.prepareStatement(sql);
        得到预先状态通道
//4.键盘录入信息
    Scanner input = new Scanner(System.in);
    System.out.println("请输入用户名:");
    String name = input.next();
    System.out.println("请输入用户密码:");
    String pass = input.next();
//5.给问号占位符添加值
    pstt.setString(1, name);
    pstt.setString(2, pass);
//执行
    rs =  pstt.executeQuery();
        执行查询操作
    while(rs.next()){
    int i = rs.getInt("id");
    String name1 = rs.getString("name");
    String pass1 = rs.getString("pass");
    System.out.println(i+"------"+name1+"------"+pass1);
    }
//释放资源
    try {
        if(rs != null){
        rs.close();
        }
        if(pstt!= null){
        pstt.close();
        }
        if(con!= null){
        con.close();
        }
        } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }

使用的时候可已将重复的操作,封装成一个util方法

Statement(状态通道)和PreparedStatement(预状态通道)的区别:

创建方式不同

    Statement sta=con.createStatement();
    状态通道


   PreparedStatement pps=con.prepareStatemnt(sql);
    预状态通道
    对sql语句进行预编译并且支持占位符
    在执行sql语句方法中不需要再添加sql语句了。
    用于解决sql注入的问题
    常用

执行sql的时机不同

   状态通道是在调用executeUpdate()和executeQuery()方法时传入sql
   预状态通道是在创建对象时就已经传入sql语句

预状态通道支持占位符的使用,注:赋值时,下标从1开始

项目分包

entity

实体包【存放的都是实体类】javabean

utils

工具包【存放的都是工具类】

dao(数据持久化层)

dao层【dao包】 【创将一个实体类就相应的要创建一个该实体类的dao类】

单元测试

在你的项目目录下创建一个dictory(根目录下面)

之后点击新创建的目录右键 mark Dictory  选择test那项

 之后进入你要测试的类中,用idea中的快捷键 ctrl+shift+t

选择JUnit4,在勾选你要测试的方法,之后点击run

 事物

con.setAutoCommit(false);//取消自动提交事务

con.commit();//提交事务

con.rollback();//回滚事务,回到数据修改前的状态

//专门为用户表服务的业务逻辑处理层   [该类中的方法发和dao中的方法是一样的]
public class AccountService {
    private Connection con = null;
    AccountDao dao = new AccountDao();

    public boolean  account(double mon,String namein,String nameout){
        try {
            //获取链接对象
            con = JDBCUtil.getCon();
            con.setAutoCommit(false);//取消自动提交
            
             boolean booout =  dao.accountJian(mon, nameout);
            boolean booin =  dao.accountJia(mon, namein);
            if(booout && booin){
                return true;
            }
        
             
             con.commit();//手动提交事务
            
        } catch (Exception e) {
            try {
                con.rollback();//事务回滚
            } catch (SQLException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
        
        return false;
    }
}

 事务的特性

原子性

原子性是指事务实施一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

一致性

事务前后数据的完整性必须保持一致

隔离性

事物的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事物所干扰,

多个并发事务之间数据要互相隔离

持久性

持久性是指一个事物一旦被提交,他对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该

对其有任何影响

PreparedStatement的批处理

当你有10条SQL语句要执行时,一次向服务器发送一条SQL语句,这么做效率上很差!处理的方案是使用批处理,即一次向服务器发送多条SQL语句,然后由服务器一次性处理。

批处理只针对更新(增、删、改)语句,批处理没有查询什么事儿!

批处理的三个方法
void】     addBatch(String sql):添加一条语句到“批”中;
int[]】     executeBatch():执行“批”中所有语句。返回值表示每条语句所影响的行数据;
void】     clearBatch():清空“批”中的所有语句。
代码
con = JdbcUtils.getConnection();
    连接对象
String sql = "insert into user values(?,?,?,?)";
    Sql语句模板
pstt = con.prepareStatement(sql);
for(int i = 0; i < 10; i++) {
    pstt.setString(1, "S_10" + i);
        设置每一列的值
    pstt.setString(2, "stu" + i);
    pstt.setInt(3, 20 + i);
    pstt.setString(4, i % 2 == 0 ? "male" : "female");
    pstt.addBatch();
        添加批次
    }

数据库属性文件的使用

 存值方式:key-value

实现方法

在src文件夹下创建一个属性文件【jdbc.properties】

MyDriver=com.mysql.jdbc.Driver
Url=jdbc\:mysql\://localhost\:3306/C1708A
Name=root
Pass=1234

读取属性文件中的信息

InputStream in=当前类名.class.getClassLoader().getResourceAsStream("jdbc.properties");
    将属性文件转换成一个流



接着创建一个properties的对象,在通过这个对象来调用一个load的方法
Properties pro=new Properties();
pro.load(in);

通过key值找value值

driver=((String) pro.get("mysqldriver")).trim();
url=((String) pro.get("url")).trim();
username=((String) pro.get("username")).trim();
password=((String) pro.get("password")).trim();

在读取属性文件的过程中有一些内容只需要执行一次

static{
    加载驱动
//获取一个资源流                                                              得到本类的加载器。在通过加载器得到一个资源流(小括号中防止的就是想要得到的资源文件)
InputStream inStream =  JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
//创建一个属性文件的对象
Properties pro = new Properties();
try {
    //使用属性文件类对象调用方法来加载资源流
    pro.load(inStream);
 driver = pro.getProperty("MyDriver");
 url = (String) pro.get("Url");
 name = (String) pro.get("Name");
 pass = (String) pro.get("Pass");
 System.out.println(JDBCUtil.class.getClass());
System.out.println(driver+"   "+url+"   "+name+"   "+pass);
//加载驱动
Class.forName(driver);
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
}

 

转载于:https://www.cnblogs.com/taozizainali/p/11046730.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值