【JavaWeb_Part03】上位的小三之使用 JDBC 操纵 MySQL

开篇

上篇文章我们说了 MySQL 中的一些常用的命令操作,相信各位对 MySQL 的一些基本操作都已经掌握了,如果说用命令行操作 MySQL 数据库是原配的话,那么今天将的使用 Java 代码来操作数据库就是小三,为什么呢?因为在人眼里,正房永远都没有小三有吸引力,有诱惑力。

好了,言归正传,下面我们对 MySQL 来讲一些进阶的处理。如果你对命令行操作数据库还是不太熟悉的话,我推荐你先去看一下前两篇文章。电梯在下面:

1、【JavaWeb_Part01】入门 MySQL 数据库
2、【JavaWeb_Part02】与 MySQL 人鬼情未了

使用 Java 代码操作数据库

既然是使用 Java 代码操作数据库,那么还是有一定的流程。下面我们来说一下具体的操作流程。

1. 加载驱动

首先我们需要加载 MySQL 的驱动,通过如下的方式注册驱动。

Class.forName("com.mysql.jdbc.Driver");

2. 获取连接

String connectionUrl = "jdbc:mysql://localhost:3306/day01";
conn = (Connection) DriverManager.getConnection(connectionUrl, username, password); //获取数据库连接

day01 表示的是数据库名称
username 表示的是数据库的用户名
password 表示的是数据库的密码

3. 创建可执行的 SQL 语句对象

Statement createStatement();
PreparedStatement prepareStatement(String sql);
CallableStatement prepareCall(String sql);

4. 执行 SQL

int executeUpate(String sql); //执行insert update delete语句
ResultSet executeQuery(String sql); //执行select语句
boolean execute(String sql); //执行select返回true 执行其他的语句返回false

5. 释放资源

释放资源就比较简单了,通过调用 Connection 和 PrepareStatement 的 close 方法即可。

public static void release(PreparedStatement pst, Connection conn){
    if(pst != null){
        try {
            pst.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if(conn != null){
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

6. 代码实现

上面的步骤已经说的很清楚了,下面我们只需要按部就班的按步骤来走就好了,这里就没什么可以讲的了,直接贴代码了,看不懂的直接在下面留言就好了。

1. 编写 JDBC 帮助类

JDBCHelper.java

public class JDBCHelper {
    private static final String driverUrl;
    private static final String connectionUrl;
    private static final String username;
    private static final String password;
    /**
     * 静态代码块,加载数据库资源
     */
    static{
        Properties properties = loadProperties();
        driverUrl = properties.getProperty("jdbcDriver");
        connectionUrl = properties.getProperty("connectionUrl");
        username = properties.getProperty("username");
        password = properties.getProperty("password");
    }

    /**
     * 加载配置文件
     */
    private static Properties loadProperties(){
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src/db.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }

    /**
     * 释放链接
     */
    public static void release(PreparedStatement pst, Connection conn){
        if(pst != null){
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 加载驱动
     */
    private static void loadDriver(){
        try {
            Class.forName(driverUrl);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     */
    public static Connection getConn(){
        loadDriver();
        Connection conn = null;
        try {
            conn = (Connection) DriverManager.getConnection(connectionUrl, username, password); //获取数据库连接
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
}
2. 编写数据库信息相关配置

我这里把数据库的相关资源抽取成了配置文件,方便修改。
db.properties

jdbcDriver=com.mysql.jdbc.Driver
connectionUrl=jdbc:mysql://localhost:3306/day01
username=root
password=这里是你的数据库密码
3. 编写操纵数据库工具类

DataUtils.java

public class DataUtils {

    /**
     * 返回影响的行数
     * @param user
     * @return
     */
    public static int insertUser(User user) {
        int executeUpdate = 0;
        PreparedStatement preparedStatement;
        Connection conn = JDBCHelper.getConn();
        /**
         * insert into user(name, sex, age) values("xxx","x", xx);
         */
        String sql = "insert into user(name, sex, age) values(?,?,?)";

        try {
            preparedStatement = (PreparedStatement) conn.prepareStatement(sql);
            preparedStatement.setString(1, user.getName());
            preparedStatement.setString(2, user.getSex());
            preparedStatement.setInt(3, user.getAge());
            executeUpdate = preparedStatement.executeUpdate();
            JDBCHelper.release(preparedStatement, conn);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return executeUpdate;
    }

    /**
     * 删除用户
     * return 返回该操作影响的行数
     */
    public static int deleteUser(String name){
        PreparedStatement preparedStatement;
        Connection conn = JDBCHelper.getConn();
        int executeUpdate = 0;
        /**
         *  delect from user where name = "荆小六";
         */
        String sql = "delete from user where name = '" + name +"'" ;

        try {
            preparedStatement = (PreparedStatement) conn.prepareStatement(sql);
            executeUpdate = preparedStatement.executeUpdate();
            JDBCHelper.release(preparedStatement, conn);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return executeUpdate;
    }

    /**
     * 更新用户
     */
    public static int updateUser(User user, int id){
        Connection conn = JDBCHelper.getConn();
        PreparedStatement preparedStatement;
        int executeUpdate = 0;
        /**
         * update user set name = 'xxx' where id = xx;
         */
        String sql = "update user set name = '" + user.getName() +"' where id = "+ id + "";
        try {
            preparedStatement = ((PreparedStatement) conn.prepareStatement(sql));
            executeUpdate = preparedStatement.executeUpdate();
            JDBCHelper.release(preparedStatement, conn);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return executeUpdate;
    }


    /**
     * 查询所有用户
     */
    public static void findAll(){
        Connection conn = JDBCHelper.getConn();
        /**
         * select * from user;
         */
        String sql = "select * from user";

        PreparedStatement preparedStatement;
        try {
            preparedStatement = (PreparedStatement)conn.prepareStatement(sql);
            ResultSet rs = preparedStatement.executeQuery();
            int col = rs.getMetaData().getColumnCount();
            System.out.println("user 表中的 field 字段为:" + col);
            System.out.println("==================user表中的数据=====================");
            while (rs.next()) {
                for (int i = 1; i <= col; i++) {
                    System.out.print(rs.getString(i) + "\t\t");
                    if ((i == 2) && (rs.getString(i).length() < 8)) {
                        System.out.print("\t\t");
                    }
                }
                System.out.println("");
            }
            System.out.println("====================================================");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
4. 编写测试类

所有的准备工作都已经准备完毕,好了,我们现在要编写我们的测试类了。
JDBCTest.java

public class JDBCTest {
    //插入用户                                                                                                   
    @Test                                                        
    public void testInsert(){                                                                                        
        User user = new User();                                  
        user.setName("nvshen");                                  
        user.setSex("M");                                        
        user.setAge(23);                                                                                           
        int i = DataUtils.insertUser(user);                      
        System.out.println("影响行数:" + i);                         

    }                                                            
    //删除用户                                                             
    @Test                                                        
    public void testDelete(){                                    
        int deleteUser = DataUtils.deleteUser("荆小六");            
        System.out.println("影响行数:" + deleteUser);                
    }                                                            

    //更新用户                                                            
    @Test                                                        
    public void testUpdate(){                                    
        User user = new User();                                  
        user.setName("孙悟空");                                     
        int updateUser = DataUtils.updateUser(user, 9);          
         System.out.println("影响行数:" + updateUser);               
    }                                                            

    @Test                                                        
    public void testFindAll(){                                   
        DataUtils.findAll();                                     
    }                                                            
}                                                                

执行结果:(PS:我这里只是执行了 findAll 方法,但是其他方法在截图中应该早已露出端倪,细心的小伙伴一看便知)

查询全部的结果

到这里,我们的 Java 代码操作数据库就已经完成了,不过,你以为这样就完了么?实际上并没有,如果你观察够仔细,你就会发现这些代码还是有一定的漏洞的。那么漏洞在哪里呢?当然是获取连接,你会发现,当我们每执行一次增删改查我们就通过 DriverManager.getConnection() 方法获取了一个连接,这显然是不合理的。

细节优化

上面已经抛出了彩蛋,那我下面自然就要想一些解决办法。如何能解决上面的问题呢?我们可以自定义一个连接池,连接池中默认放置 5 个连接,当我们需要链接的时候,直接去链接池中取,用完后再归还链接会链接池;如果连接池中的链接不够用了,那么我们就可以再放置 3 个连接进去。。。嗯?等等,这个东西的实现原理怎么好像见过? 没错,这就是市面上的一些链接池的套路,比如 c3p0, dbcp 等等,只不过我们现在是自己来实现,而他们封装的更好一点。这些东西,当然要知其然而知其所以然,这样才能在平时的工作中做到游刃有余。

可能有些人还不是太懂连接池,既然这样,那我就在这里科普一下连接池吧。

Connection 对象在 JDBC使用的时候,使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了。每次创建和销毁对象都是耗时操作,需要使用连接池对其进行优化。程序初始化的时候,初始化多个连接,将多个连接放入到池中(内存中)。每次获取的时候,都可以直接从连接池中进行获取。使用结束以后,将连接归还到池中。

好了,说干就干,我们新建一个 ArrayList 去存储连接,具体实现代码如下。

public class MyDataSource implements DataSource{
    List<Connection> list = new ArrayList<Connection>();
    //初始化连接池的个数
    public  MyDataSource() {
        for (int i = 1; i <= 5; i++) {
            Connection conn = JDBCHelper.getConnection();
            list.add(conn);
        }
    }

    @Override
    // 从连接池中获得连接
    public Connection getConnection() throws SQLException {
        if(list.size()==0){
            for (int i = 1; i <= 3; i++) {
                Connection conn = JDBCHelper.getConnection();
                list.add(conn);
            }
        }
        Connection conn = list.remove(0);
        return conn;
    }
    // 归还连接
    public void addBack(Connection conn){
        list.add(conn);
    }
}

上面的代码并不完整,但是大致思路是这样的,这就是整个自定义连接池的流程。

结语

到这里,我们使用 Java 代码操作 MySQL 数据库的操作就已经基本上完成了。大致就是这样,由于本人能力有限,写出的代码难免会有错误,如有错误,还请各位大神不吝赐教,同时也欢迎各位小朋友留言与我交流。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值