笔记:Jdbc

必要声明:参考B站up主 写给李华的信 (传智播客)
代码部分没有打上try catch 和 throw 的异常处理

Jdbc概念+快速入门

1、概念:官方Sun公司定义的一套操作所有关系型数据库的规则,即接口。各厂商去实现这套接口,即提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

2、快速入门

//1、导入驱动jar包
//2、注册驱动
Class.forName("com.mysql.jdbc.Driver");   //【要理解】
//3、捕获数据库连接对象
Connection conn = DriverManager.getConnection(url"jdbc:mysql://localhost:3306/db3",user"root",password"mysql_native password");
//4、定义sql语句
String sql = "update account balance = 500 where id = 1";
//5、获取执行sql的对象Statement
Statement stmt = conn.createStatement();
//6、执行sql语句
int count = stmt.executeUpdate(sql);
//7、处理结果
System.out.println(count);
//8、释放资源
stmt.close();
conn.close();

代码理解要点:注册驱动–加载进内存
注意:若涉及try catch时抽取变量:Connection conn = null; Statement stmt = null

各类详解

DriverManager

1、注册驱动:告诉程序该使用哪个数据库驱动jar包
static void registerDriver(Driver driver);
写代码使用:Class.forName(“com.mysql.jdbc.Driver”); //存在静态代码块含registerDriver(new Driver)
2、获得数据库连接
static Connection getConnection(String url, String user, String password);

Connection

1、获取执行sql的对象
Statement createStatement();
PreparedStatement preparedStatement(String sql);
2、管理事务

Statement

执行sql:
int executeUpdate(String sql); //执行DML(insert delete uppdate) DDL(create alter drop)
ResultSet executeQuery(String sql); //执行DQL(select) 结果集

ResultSet:结果集对象,封装查询结果

1、next();
boolean next() : 游标下移一行,如果此行有数据,true ; 无数据,false
getXxx(参数) 如: int getInt( ) , String getString()
参数:1、int:getString(1);
2、string : getdouble(“age”);

//1.注册驱动
//2.获取连接对象
//3.定义sql
 String sql = "select *from account";
//4.获取执行sql对象
//5.执行sql语句
 rs = stmt.executeQuery(sql);     //已经抽取到外面
 //6.处理结果
    //6.1让游标下移一行
 rs.next();
    //6.2获取数据
 int id = rs.getInt(1);
 Sting name = rs.getSting("name");
 System.out.println(id + "---"+ name );
 //7.释放资源

2、处理结果的改进----遍历
while(rs.next())
{
获取数据
}
3、定义方法:查询emp表的数据,将其封装为对象,然后装载集合,返回
表->类 / 每一行的数据->一个对象(用)
*定义Emp类
*定义方法public List findAll(){}
*实现方法 select *from Emp

//主
public class JdbcDemo1{
  public static void main(String[] args){
  List<Emp> list = new JdbcDemo1.findAll();
  System.out.println(list);
  System.out.println(list.size());
}
}

public List<Emp> findAll(){ 
//抽取部分
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

//1.注册
//2.获取连接对象
//3.定义sql
//4.获取执行sql对象
//5.执行sql
//6.遍历结果集,封装对象,装载集合
Emp emp = null;  //【理解】
List<Emp> list = new ArrayList<Emp>();   //抽取到外面
while(rs.next()){
//获取数据
int id = rs.getInt("id");
String name = rs.getName("name");
//创建对象,赋值
emp = new Emp();
emp.setInt(id);
emp.setString(name);
//装载集合
list.add(emp);
//释放资源
finaly{
  if(rs!=null){
  rs.close();  //还有stmt\conn
  }
}
}
}

Jdbc工具类——登录案例

需求:录入用户名和密码;判断用户是否登陆成功
1.创建数据库表user
CREATE TABLE USER{
id INT PRIMARY AUTO_INCREMENT,
username VARCHAR(32),
password VARCHAR(32)
}

public class JDBCDemo{  

   public static void main(String[] args){
     //1.键盘输入
     Scanner sc = new Scanner(System.in);
     System.out.println("请输入用户名");  //密码也是
     sc.nextLine();
     //2.调用方法  login是非静态方法:所以要创建对象
     boolean flag = new JDBCDemo().login(username,password);
     if(flag){
     System.out.println("登陆成功")}else{
     System.out.println("用户名或密码失败")}
   }
  //登录方法
  public boolean login(String username, String password){
    if(username == null || password == null){
       return false;
    }
    //连接数据库判断是否登陆成功
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    //1.
    conn = JDBCUtils.getConnection()
    //2.
    String sql = "select *from user where username = '"+username+"' and password = '"+password+"'";
    //3.
    stmt = conn.createStatement();
    //4.
    rs = stmt.executeQuery(sql);
    //5.判断
    return rs.next();
    //要用finally
    finally{
      JDBCUtils.close(rs,stmt,conn);
    }
     return false;
  }
}

【总结】
1.注册驱动也抽取,但一般不是放在一个方法里
2.抽取一个方法:获取连接对象
( 需求:不想传递参数麻烦,保证工具类的通用性:配置文件)
配置文件:properties url= user= password= driver=
【文件的读取,只需一次读取来得到值(getConnection ),使用静态代码块】
声明url user password三个静态成员变量
以及为了注册驱动:声明 private static String driver
静态代码块
static{
//读取资源文件,获取值 BufferReader FileReader 麻烦
//propeerties集合类
Properties pro = new Properties();

  //获取src路径下的文件的方式-->ClassLoader  类加载器(加载进内存)

ClassLoader classloader = JDBCUtils.class.getClassLoader();
URL res = classloader.getResource("jdbc.properties);
String path = res.getPath();
System.out.println(path);

//有bug
//加载文件 load可接受reader 和 inputStream 字符流 字节流 麻烦~~
add(new FileReader(“src/jdbc.properties”)); 绝对路径

//获取数据,赋值
url = pro.getPeoperties("url");  /还有user  password  driver
//注册驱动
Class.forName(driver);

}

public static Connection getConnection(){
return DriverManager.getConnection(url,user,password);
}
3.抽取一个方法:释放资源
public static void close(Statement stmt,Connection conn){
if(conn!=null){ //当然还有stmt
conn.close(); //要try catch
}
}

**可以重载有三个参数的

PreparedStatement:执行sql对象

1.SQL注入问题: 用户随便输入dsbhv,输入密码:a’ or ‘a’ = 'a
select *from user where username = ‘dsbhv’ and passwoord = ‘a’ or ‘a’ == ‘a’;
2.解决SQL注入:使用preparedstatement对象(预编译sql: 参数使用?占位符)

后期使用preparedStatement来完成增删查改的操作
//1.导入jar包
//2.注入驱动
//3.获取数据库连接对象connection
//4.定义sql
? ?
//5.获取执行sql的对象
PreparedStatement pstmt = Connection.PreparedStatement(String sql)
//6.赋值?
setXxx(参数1,参数2);
//7.执行sql,接受返回结果,不需要传递sql
executeQuery();
//8.处理结果
//9.释放资源

事务管理

1.开启事务:setAutoCommit(boolean autoCommit): 调用参数false则开启
2.提交事务:commit() ----没有异常时
3.回滚事务: rollback() ----出现异常时

数据库连接池(数据源DataSource)

1.本质:一个(存放数据库连接的)容器
系统初始化—容器创建—容器申请连接对象
2. 基本实现
标准接口:DataSource java.sql包下的(一般由厂商实现:C3P0 Druid)
接口中的方法:获取getConnection()
归还Connection.close()

C3P0 数据库池连接技术

1.基本使用
*导入2个jar包
*定义配置文件:名称 c3p0.properties 或 c3p0-config.xml
路径 直接将文件放在src目录下
*创建数据库连接对象——核心对象 ComboPooledDataSource
*获取连接:getConnection

public class c3p0Domo1{
      public static void main(String[] args){
      //1.导包
      //2.创建数据库连接池对象(使用了默认配置)
      DataSource ds = ComboPooledSource();
      Connection conn = ds.getConnection();
      //3.打印
      System.out.println(conn);
     }
}

2.若指定配置文件
DataSource ds = new ComboPooledSource(“etherc3p0”)
3.当指定配置文件中的连接对象少:
if(i==5){
conn.close(); //归还连接
}

Druid

1.基本使用
*导包 druid-1.0.9.jar
*定义配置文件:是以properties形式的; 可叫任意名称,放在任意目录
*获取数据库连接池对象:通过工厂来获取 DruidDataSourceFactory
* 获取连接:getConnection()

//1.导包到lib目录下
//2.定义配置文件  druid.properties文件(文件里有参数) 放到src目录下
//3.加载配置文件
Properties pro = new Properties();
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//4.获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource();
//5.获取连接
Connection conn = ds.getConnection();
System.out.println(conn);

Druid工具类

1.定义一个类 JDBCUtils
2.提供静态代码块加载配置文件,初始化连接池对象
3.提供方法
*获取连接方法:通过数据库连接池获取连接对象
*释放资源
*获取连接池的方法

public class JDBCUtils{
      //定义成员变量
      private static DataSource ds;
     
     //静态代码块
     static{
            //1.加载配置文件
            Properties pro = new Properties();
                                             pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
           //2.获取DataSource
           ds = DruidDataSourceFactory.createDataSource(pro);            
         }    

     //获取连接
     public static Connection getConnection(){
     return ds.getConnection();
     }

    //释放资源
    public static void close(Statement stmt,Connection conn){
     if(stmt!=null){
       stmt.close();
     }
     if(conn!=null){
       conn.close();   //归还连接
     }
    }

    //释放资源的重载
    public static void close(ResultSet rs,Statement stmt,Connection conn){
        if...rs
        if...stmt
        if...conn  //归还连接
    }
  
  //获取连接池方法
  public static DataSource getDataSource(){
      return ds;
   }
}

注意:释放资源部分可以简化(含有重载)
//两个参数的
public static void close(Statement stmt,Connection conn){
close(null,stmt,conn);
}
//三个参数的
public static void close(ResultSet rs,Statement stmt,Connection conn){
if…rs;
if…stmt;
if…conn;
}

测试工具类 : 完成添加操作,给account表添加一条记录

public static void main(String[] args){
Connection conn = null;
PreparedStatement pstmt = null;
//1.获取连接
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "insert into account value(null,?,?)";
//3.获取pstmt对象
pstmt = conn.preparedStatement(sql);
//4.给问号赋值
pstmt.setString(1,"王五");
pstmt.setDouble(2,3000);
//5.执行sql
int count = pstmt.executeUpdate();
System.out.println(count);
//6.释放资源
finally{
   JDBCUtils.close(pstmt,conn);
}
}

JdbcTemplate ----完成CRUD操作

  • update(): 执行增删查改的DML操作
  • queryForMap(): 查询结果将结果集封装到map集合
    将列名作key 值作为value 将这条记录封装为一个map集合
  • queryForList(): 查询结果将结果集封装到List集合
    【注意】:将每条记录封装为一个Map集合,再将Map集合装载到List集合
  • query(): 查询结果,将结果封装为JavaBean对象
    *query的参数:RowMapper
    *一般我们使用BeanPropertyRowMapper实现类,可以完成数据JavaBean的自动封装
    * new BeanPropertyRowMapper<类型>(类型.class)
  • queryForObject(): 查询结果,将结果封装为对象
    一般用于聚合函数的查询
    1.快速入门
public static void main(String[] args){
//1.导入几个包
//2.创建JDBCTemplate对象
JDBCTemplate template = new JDBCTemplate(JDBCUtils.getDataSource());
//3.调用方法
String sql = "update account set balance = 5000 where id = ?";
int count = template.update(sql,3);   //合并了执行SQL和设定值
System.out.println(count);
}

DML执行语句

0.Junit.Test单元测试—让方法独立执行
public static void main(String[] args){
@Test
public void test1(){
System.out.println("执行了…“);
//如果这里有错误 int i = 3/0; 会出现红色提示
}

    @Test
    public void test2(){
       System.out.println("又被执行...")
   }

}

1.修改1号数据的 salary 为 10000
***先创建一个Emp类

public static void main(String[] args){
 //1.获取JDBCTemplate对象
 JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); 
 
 @Test
 public void test1(){
 //2.定义sql
 String sql = "update emp set salary = 10000 where id = 1";
 //3.执行sql
 int count = template.update(sql);
 System.out.println(count);   
  }

@Test
test2(){
    String sql = "insert into emp(id,ename,dept_id)values(?,?,?)";
    int count = template.update(sql,001,"殷素素"10)
    System
}

@Test
test3(){
     String sql = "delete from emp where id = ?"
     int count = template.update(sql,001)
     System
}
}

2.添加一条记录
3.删除刚才添加的记录

DQL

4.查询id = 1所有的记录,将其封装为Map集合

@Test  4
String sql = "select *from emp where id = ?";
Map<String,Object> map = template.queryForMap(sql,001);
System.out.println(map);

@Test  5   【没有简化】
public void test5(){
    String sql = "select *from emp";
    List<Map><String,Object> list = template.queryForList(sql);
    for(Map<String, Object> stringObjectMap : list){
      System.out.println(stringObjectMap);
    }

@Test  6.1
String sql = "select *from emp";
List<Emp> list = template.query(sql,new RowMapper<Emp>(){
 
 @Override
 public Emp mapRow(ResultSet rs,int i){
    Emp emp = new Emp();
    int id = rs.getInt("id");
    String ename = rs.getString("ename");
    Date joindate = rs.getDate("joindate");

    emp.setId(id);
    ename
    emp.joindate(joindate);
  
   return emp;
 }
}); 
 for(Emp emp : list){
   System.out.println(emp);
 }

@Test  6.2  用别人提供的实现类
public void test62(){
  String sql = "select *from emp";
  List<Emp> list = template.query(sql,new BeanPropertyRowMapper<Emp>(Emp.class));
  for (Emp emp : list){
  System.out.println(emp);
  }
}

@Test7
public void test7(){
  String sql = "select count(id) from emp"
  Long total = template.queryForObject(sql,Long.class);        //queryForObject是用来查询一些聚合函数
  System.out.println(total);
}

5.查询所有记录,j将其封装为List
6.查询所有记录,将其封装为Emp对象的List集合
7.查询总记录数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值