JAVA学习日志2-5(JDBC)

JAVA学习日志2-5(JDBC)

JDBC
jdbc的全称是 java database connection,是java和数据库连接的桥梁。jdbc是java提供的一个接口或者是规范,具体的实现是由各个数据库厂商来完成的。所有不同的数据库需要不同的jabc驱动包。

  • jabc中一些常用的接口和类

    接口或类
    DriverManager(类)驱动管理类,用于注册驱动
    Connection(接口)连接对象,用于连接数据库
    Statemnet(接口)执行sql的对象,用于发送sql给数据库
    ResultSet(接口)结果集,用于获取获取查询结果
  • jdbc连接数据的基本的步骤
    1.加载驱动
    2.获取连接对象
    3.得到执行sql的对象
    4.获取结果集
    5.关闭资源

  • jdbc 连接mysql数据库

  1. 下载用于mysql的驱动包,mysql官网下载:https://dev.mysql.com/downloads/connector/j/5.1.html
  2. 为jar包添加依赖(Idea)
    新建一个lib目录用来存放jar包,然后添加依赖
    在这里插入图片描述
    (可以在添加一个juint的jar包,可以使 public void 的方法不用去主函数中就可以直接执行,但要在方法前添加注解 @Test)
  3. 依赖添加成功后,就可以通过下面的代码连接了
//通过反射加载驱动
  Class.forName("com.mysql.jdbc.Driver");
/*通过连接管理对象获取对象,其中 jdbc:使用jdbc来连接数据(主协议),mysql:连接mysql数据库
(子协议),localhost:3306 主机地址及端口号,mydb2 数据库名,characterEncoding=utf-8 表示
设置其编码格式,后面的两个root分别为数据库的用户名和密码*/
  Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb2?characterEncoding=utf-8", "root", "root");           
//通过连接对象 获取到执行sql 的对象
  Statement sta = conn.createStatement();
//执行sql语句 增 删 改 使用.executeUpdata(sql) 返回的是int类型的数据,表示影响的行数
  String sql = " insert into tab1 values(2,'lili')";
  sta.executeUpdate(sql);
//执行sql语句 查询 时使用.executeQuery(sql) 返回的是ResultSet类型的数据,表示查询结果,需要遍历获取到每个值
  String sql = "select * from stu;";
  ResultSet rs = sta.executeQuery(sql);
  while(rs.next()){
  //获取当前行的第一列元素,也可以通过字段名来获取 
  //String sid = rs.getString("sid");
  	String sid = rs.getString(1);
	String sname = rs.getString(2);
	int age = rs.getInt(3);
	System.out.println(sid+"\t"+sname+"\t"+age);
  }

PrepareStatement 对象
使用Statement 对象执行sql语句当sql语句有具体值传递是,需要用到字符串的拼接

Scanner sc = new Scanner(System.in);
String str = sc.next();
int num = sc.nextInt();
Statement sta = conn.createStatement();
String sql = "select * from stu where sid='"+str+"' and age ="+num;
ResultSet rs= sta.executeQuery(sql);

这样虽然可以找到正确的数据,但存在sql注入的问题,如 str赋值为 1’or’1’=‘1’# ,num赋值为1,则实际执行的sql语句是

select * from stu where sid='1'or'1'='1'#' and age =1

#号后面的内容sql语句都判断为了注释,前半部分中无论sid是否有1这样的值,‘1’='1’是恒成立的,通过or连接后这条sql语句就会正常执行了,如果这个方法使用在一个登陆验证是非常危险的。

PrepareStatement 不拼接字符串,动态参数可以使用占位符来进行替换这样就消除的sql注入。(PrepareStatement 是 Statement的子类)

String sql = "insert into stu  values (?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
//把第一个占位符的值设置成"S_1022"
ps.setString(1,"S_1022");
ps.setString(2,"luiui");
ps.setInt(3,45);
ps.setString(4,"male");
//执行时,不需要在传递sql语句了
ps.executeUpdate();

jdbc工具类的封装
每次向数据库发生sql语句时,都需要加载驱动,建立连接,创建执行sql的对象,执行sql这其中有很多公共的部分,可以进行抽取。

  • 加载驱动和建立连接的封装
    驱动加载可能会因为数据库的不同加载不同的驱动,建立链接时可能连接的数据库不同url也就不同,所以可以把这些信息放在配置文件里。返回Connection类型。

    文件存储的内容:
    在这里插入图片描述
    文件读取的工具类(单例设计模式)(读取时按key取值):

    public class PropertiesUtils {
    
      private static PropertiesUtils proU;
      private Properties pro;
      private PropertiesUtils(){
          pro = new Properties();
          try {
              FileInputStream fis = new FileInputStream("database.properties");
              pro.load(fis);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
    
      public static PropertiesUtils getInstanceOf(){
          if(proU==null){
              synchronized (PropertiesUtils.class){
                  if(proU==null){
                      proU = new  PropertiesUtils();
                  }
              }
          }
    
          return proU;
      }
    
      public String getValue(String key){
          String value = pro.getProperty(key);
          return value;
      }
    }
    

    BaseDAO类里的封装

    public Connection getconn(){
          Connection conn = null;
          try {
              Class.forName(PropertiesUtils.getInstanceOf().getValue("jdbc.driver"));
              conn = DriverManager.getConnection(PropertiesUtils.getInstanceOf().getValue("jdbc.url"),PropertiesUtils.getInstanceOf().getValue("jdbc.username"),PropertiesUtils.getInstanceOf().getValue("jdbc.password"));
          } catch (ClassNotFoundException e) {
              e.printStackTrace();
          } catch (SQLException e) {
              e.printStackTrace();
          }
          return conn;
      }
    
  • 执行sql对象的封装
    执行sql的对象可以分为两大类,1.增 删 改 操作的sql返回的是int类型,使用.executeUpdate() 2.查询 的sql 返回ResultSet类型,使用.executeQuery().

    增 删 改的封装,封装成一个方法后需要两个参数,一个参数是带有占位符的sql语句,一个参数是每个占位符的具体值,每个具体值肯不同所有采用object数组

    public int update(String sql,Object[] obj){
          int num = -1;
          Connection conn = getconn();
          PreparedStatement ps = null;
          try {
               ps = conn.prepareStatement(sql);
               //给每个占位符赋值
              if(obj!=null&&obj.length>0){
                  for(int i=0;i<obj.length;i++){
                      ps.setObject(i+1,obj[i]);
                  }
              }
              num = ps.executeUpdate();
          } catch (SQLException e) {
              e.printStackTrace();
          }finally {
              close(null,ps,conn);
          }
          return num;
      }
    

    查询 的封装,查询结果可以与实体类对应,这里是Pet类,返回list对象

    public List query(String sql,Object[] obj){
          List<Pet> list = new ArrayList<Pet>();
          Connection conn = getconn();
          PreparedStatement ps = null;
          ResultSet rs = null;
          try {
               ps= conn.prepareStatement(sql);
              if(obj !=null&&obj.length>0){
                  for(int i=0;i<obj.length;i++){
                      ps.setObject(i+1,obj[i]);
                  }
              }
               rs = ps.executeQuery();
              while(rs.next()){
                  int id = rs.getInt("id");
                  String name= rs.getString("name");
                  int health = rs.getInt("health");
                  int love = rs.getInt("love");
                  String strain = rs.getString("strain");
                  Pet pet = new Pet(id,name,health,love,strain);
                  list.add(pet);
              }
          } catch (SQLException e) {
              e.printStackTrace();
          }finally {
              close(rs,ps,conn);
          }
          return list;
      }
    
  • 关闭资源的封装

    public void close(ResultSet rs,PreparedStatement ps,Connection conn){
          try {
              if(rs!=null) rs.close();
              if(ps!=null) ps.close();
              if(conn!=null) conn.close();
          } catch (SQLException e) {
              e.printStackTrace();
          }
      }
    

BaseDAO工具类的调用

    @Test
    public void updatePetById(){
        String sql = "update pet set name=?  where id=?";
        Object[] obj = new Object[]{"zhuzi", 1};
        BaseDAO base = new BaseDAO();
        int num = base.update(sql,obj);
        if(num>0){
            System.out.println("修改成功!");
        }
    }
    @Test
    public void find(){
        String sql = "select * from  pet where name like ?";
        Object[] obj = new Object[]{"%a%"};
        BaseDAO base = new BaseDAO();
        List<Pet> list = base.query(sql,obj);
        for(Pet temp : list){
            System.out.println(temp);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值