java与数据库的关系

163 阅读5分钟

java的反射

java反射的原理

java文件--->class文件--->jvm放入内存进行运行。这个是jvm的运行的原理,但是事实上的操作是。把java文件变成了class的文件,在文件里边有Constructor用于放java里边的构造方法。Field放的是java的字段。Method放的是java的方法。

所以记住:

class
Constructor
Field
Method

获取类文件的类对象

-->类名.class

-->对象.getClass()

-->Class.forName("包名.类名");

获取类的所有的构造方法

    public static void main(String[] args) throws Exception {
        //获取类
        Class classPerson=Class.forName("com.hu.Person");
        //通过类获取构造函数,获取有两个参数的构造函数.如果不加参数获取所有的构造函数,接收的是一个数组。
        Constructor c=classPerson.getConstructor(String.class,String.class);
        //通过构造函数获取一个对象
        Person p=(Person) c.newInstance("张三","男");
        System.out.println(p);
    }

关于属性的操作Field

 /**
         * 关于属性的操作
         * */
        //不管是私有的属性还是公有的属性都可以操作的方法是
        Field f=classPerson.getDeclaredField("name");
        //如果对这个属性进行修改,则需要对属性进行修改的确认。
        f.setAccessible(true);
        //进行修改
        f.set(p,"王五");
        System.out.println("------------------"+p);
        //获取值f属性的值。表示的p对象中f属性的值。
        Object obj=f.get(p);
        System.out.println("obj:"+obj);
        

关于反射的Method

/**
         * 方法Method的使用
         * */
        //获取公有方法和私有方法,不管是公有还是私有多是ok的。除了方法名以外,后边是参数的类型。
        Method method=classPerson.getDeclaredMethod("eat",String.class);
        //方法的执行。哪个对象的这个方法,后天是参数。
        method.invoke(p,"苹果");
        //私有方法可以被修改值的确认
        method.setAccessible(true);
        //方法的返回值
        String value=(String)method.invoke(p,"樱桃");
        System.out.println(value);
        

java中的jdbc相关内容

jdbc链接数据库首先需要的是一个数据库的驱动。

这里的java链接的是mysql的数据库。所以用的是mysql的jar包为:mysql-connector-java-5.1.7-bin.jar

具体链接数据库的代码如下:

import java.sql.*;

public class Demo {

    public static void demo1() throws ClassNotFoundException, SQLException {
        Connection con=null;
        Statement stmt=null;
        ResultSet rs=null;
        //1,加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //获取链接
        con = DriverManager.getConnection
                ("jdbc:mysql://localhost:3306/jdbctest","root","a1234567");
        //获取执行的Statement
        stmt=con.createStatement();
        String sql="select * from user";
        //执行后获取的结果
        rs=stmt.executeQuery(sql);
        //循环这个结果集
        while (rs.next()){
            //获取结果集中的内容,按照结果集中的类型进行获取
            System.out.print(rs.getInt("id"));
            System.out.print(rs.getString("name"));
            System.out.println();
        }

        //关闭这些资源
        if(rs!=null){
            rs.close();
        }
        if(stmt!=null){
            stmt.close();
        }
        if(con!=null){
            con.close();
        }
    }

    public static void main(String[] args) {
        try {
            demo1();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}


属性文件的使用

属性文件的文件名和后缀是: fileName.properties

需要用到Properties这个类。生成这个类的实例,然后加载properties文件的流。就可以对文件里边的内容进行相关的操作了。如下的代码:


static{
        //加载属性文件并且解析
        Properties props=new Properties();
        //读取properties文件流,这个差不多是个固定的写法。properties文件放在src的目录下才可以
        InputStream is=JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            props.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //props加载流后就可以读取文件里边的内容了
        driverClass=props.getProperty("driverClass");
        url=props.getProperty("url");
        username=props.getProperty("username");
        password=props.getProperty("password");
    }

jdbc的工具类的实现

如下代码:

package com.hu.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
    private static final String  driverClass;
    private static final String  url;
    private static final String  username;
    private static final String  password;


    static{
        //加载属性文件并且解析
        Properties props=new Properties();
        //读取properties文件流,这个差不多是个固定的写法。properties文件放在src的目录下才可以
        InputStream is=JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            props.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //props加载流后就可以读取文件里边的内容了
        driverClass=props.getProperty("driverClass");
        url=props.getProperty("url");
        username=props.getProperty("username");
        password=props.getProperty("password");
    }
    //加载驱动
    public static void loadDriver(){
        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //获取连接数据的链接
    public static Connection getConnection(){
        //先驱动起来
        loadDriver();
        Connection con= null;
        try {
            //获取链接数据库的链接
            con = DriverManager.getConnection(url,username,password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return con;
    }

    /*关闭流,需要写两个方法,这两个方法说加载的方法。一个是查询的方法,一个是增删改的方法*/
    //增删改的关闭流的方法
    public static void closeStream(Connection con, Statement stmt){
        _closeStream(con,stmt);

    }

    //改的关闭流的方法
    public static void closeStream( ResultSet rs,Connection con, Statement stmt){
        _closeStream(con,stmt);
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            rs=null;
        }



    }

    private static void _closeStream(Connection con,Statement stmt){
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            stmt=null;
        }
        if(con!=null){
            try {
                con.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            con=null;
        }
    }
}

sql的注入问题

实际的代码如下:

因为sql注入用的是sql的关键字进行传入注册的。

我们使用PreparedStatment这个类。对sql语句先进行预编译,然后再传入进来变量。这时传入进来的变量就起不到作用,因为sql语句已经结构化了,传入进来的只是作为数据而已。

public static boolean login(String name){
        boolean flag=false;
        PreparedStatement pstmt=null;
        Connection con=JDBCUtils.getConnection();
        /*防止sql的注入,我们需要用preparedStatement 这个会先对sql语句进行预编译,
        然后再传入变量。这样的话即使变量里边有关键字也不会起到效果。因为sql语句的结构固定,传入进来的不管是什么关键字
        都只会当做用户名,如果是密码就是只会当做密码
        */
        String sql="select * from user where name=?";
        try {
            //会对上边的sql语句进行预编译
            pstmt=con.prepareStatement(sql);
            //预编译之后对第几个问号填写什么变量
            pstmt.setString(1,name);
            //然后执行查询语句,因为之前sql已经预编译了,所以无需再传入sql语句
            ResultSet rs=pstmt.executeQuery();

            if(rs.next()){
                flag=true;
            }
            //关闭资源
            JDBCUtils.closeStream(rs,con,pstmt);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return flag;
    }

数据池链接数据库

有点:能够提升性能。客户端到数据池获取链接就可以。因为链接数据库是非常耗费性能的。

我们这里是以c3p0数据池jar包为例。

代码如下:

 package com.hu.jdbc;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class C3P0Test {
    public static void main(String[] args) {
        demo1();
    }


    public static void demo1(){
        PreparedStatement pstmt=null;
        Connection conn=null;
        ResultSet rs=null;
        //创建一个数据池
        ComboPooledDataSource dataSource=new ComboPooledDataSource();
        //设置这个数据池的配置
        try {
            //设置驱动
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            //设置链接的地址
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbctest");
            //设置登录的用户名
            dataSource.setUser("root");
            //设置登录的密码
            dataSource.setPassword("a1234567");
            //设置最大的链接数
            dataSource.setMaxPoolSize(20);
            //设置初始时的链接数
            dataSource.setInitialPoolSize(3);

            //获取数据库的链接
            conn=dataSource.getConnection();
            String sql="select * from user";
            //生成预编译对象
            pstmt=conn.prepareStatement(sql);
            //执行sql语句
            rs=pstmt.executeQuery();
            while (rs.next()){
                System.out.print(rs.getInt("id")+"  ");
                System.out.print(rs.getString("name"));
                System.out.println();
            }


        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if(pstmt!=null){
                try {
                    pstmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

    }
}