zoukankan      html  css  js  c++  java
  • Servlet Java Web开发(5)数据库的使用

    1经典使用

    核心API及其使用,maven:mysql-connector-java

    连接数据库

    String db_url="jdbc:mysql://localhost:3306/djangoserverTimezone=GMT%2B8";

    Connection con=DriverManager.getConnection(db_url,user,pwd);

    操作

    Statement stmt=con.createStatement();

    对于增加,修改,删除使用stmt.executeUpdate,返回作用的行数

    对于查询使用stmt.executeQuery,返回ResultSet对象,比如叫rs。获取数据方式如下

    while(rs.next()){

    ...String id=rs.getInt("id");..}

    例子

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class MainFIle {
    
        /**
         * @param args
         * @throws ClassNotFoundException 
         */
        public static void main(String[] args) throws ClassNotFoundException {
            // TODO Auto-generated method stub
            String jdbc_driver="com.mysql.cj.jdbc.Driver";
            String db_url="jdbc:mysql://localhost:3306/django?serverTimezone=GMT%2B8";
            String user="root";
            String pwd="123456";
            Connection con=null;
            java.sql.Statement stmt=null;
            try {
                con=DriverManager.getConnection(db_url,user,pwd);
                stmt=con.createStatement();
                String sql="select * from personinfo";
                ResultSet rs=stmt.executeQuery(sql);
                while(rs.next()) {
                    int id=rs.getInt("id");
                    String name=rs.getString("name");
                    String job=rs.getString("job");
                    System.out.println("well,here is your data: id is "+id+"with name: "+name+" and job:"+job);
                }
                rs.close();
                stmt.close();
                con.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                try {
                    if(stmt!=null)
                        stmt.close();
                }catch(Exception ex) {
                    ex.printStackTrace();
                }
                
                try {
                    if(con!=null)
                        con.close();}
                    catch(Exception ex) {
                        ex.printStackTrace();
                    }
                }
        }
    }
    View Code

    PreparedStatement

    是Statement的子接口,可以提高效率和防止SQL攻击。

    使用:使用sql语句模板,用户数据字符串用?代替

    String sql="insert into user value(?,?,?)";

    String update="update user set username=?,password=? where id=?";

    声明变量,和设置数据,序号从1开始

    PreparedStatement ps=con.prepareStatement(update);

    ps.setString(1,"haha");ps.setString(2,"234");

    ps.executeUpdate()或者其他

    需要执行其他数据,先清理,ps.clearParameters();

    批处理:

    在一次设置好所有数据之后,可以暂不执行,调用ps.addBatch(),再继续设置数据

    最后一次性ps.executeBatch()

    存取二进制数据

    二进制在表中的数据类型为BLOB,在代码中操作的数据类型为InputStream

    建表时,该列字段为MDDIUMBLOB (16MB)或者LONGBLOB(4GB),字段名为mydata

    将数据读入一个InputStream in中,使用PreparedStatement构建sql模板比如

    String sql="insert into yourtable (filename,mydata) values(?,?)";

    使用ps .setBinaryStream(2,in);

     读取时,使用ResultSet的getBinaryStream("mydata")方法获取InputStream对象

    方法2:存取的时候使用PreparedStatement的setBlob和

    ResultSet的getBlob方法。

    Blob 对象和字节数组可以相互转换。Blob b=new SerialBlob(..)参数是byte[]

    getBlob返回一个Blob对象b后,使用getBytes返回byte array

    DAO模式

    就是写一个类,封装访问数据的代码,在数据库和业务逻辑之间。

    1.实体域,比如我们操作的是User表,先写一个User类

    public class User{

    private String id;

    private String userName;...}

    2.DAO模式需要一个DAO接口

    public interface UserDao{

    public void add(User user);

    public void mod(User user);

    public void del(String id);....}

    3该接口的一个实现,实现具体访问数据库的细节。

    JdbcUtils辅助类

    目的:将mysql路径,用户名密码放到配置文件中。

     2.事务和连接池

    事务开始,

    执行多条sql语句

    要么提交要么回滚

    1开启事务

    setAutoCommit(false),默认为true,也就是每一条sql语句都是一个单独的事务

    2commit  or rollback

    try {

      con.setAutoCommit(false);//开启事务…

      ….

      …

      con.commit();//try的最后提交事务

    } catch() {

      con.rollback();//回滚事务

    }

     连接池库C3P0

    在src文件夹建立c3p0-config.xml文件,内容

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
        <!-- 这是默认配置信息 -->
        <default-config> 
            <!-- 连接四大参数配置 -->
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/customers</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="user">root</property>
            <property name="password">123</property>
            <!-- 池参数配置 -->
            <property name="acquireIncrement">3</property>
            <property name="initialPoolSize">10</property>
            <property name="minPoolSize">2</property>
            <property name="maxPoolSize">10</property>
        </default-config>
        
        <!-- 专门为oracle提供的配置信息 -->
        <named-config name="oracle-config"> 
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="user">root</property>
            <property name="password">123</property>
            <property name="acquireIncrement">3</property>
            <property name="initialPoolSize">10</property>
            <property name="minPoolSize">2</property>
            <property name="maxPoolSize">10</property>
        </named-config>
    
    </c3p0-config>

    使用,需要的时候直接从池中getConnection,用完关闭。

    ComboPooledDataSource ds = new ComboPooledDataSource();
    Connection con = ds.getConnection();
    ...........
    con.close();

    基于ThreadLocal的Jdbc实用类

    该类保证了一个变量,在不同的线程有一个唯一对象

    ThreadLocal<T>简介,内部是个map,使用当前线程作为键。

    ThreadLocal<Connection> con=new ThreadLocal<Connection>();

    con保证了每一个线程con都有一个Connection对象。主要三个方法

    void set(T value);  

    T get();

    void remove();

    该实用类的全部代码

    package cn.itcast.jdbc;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    /**
     * 使用本类的方法,必须提供c3p0-copnfig.xml文件
     * @author qdmmy6
     */
    public class JdbcUtils {
        // 饿汉式
        private static DataSource ds = new ComboPooledDataSource();
        
        /**
         * 它为null表示没有事务
         * 它不为null表示有事务
         * 当开启事务时,需要给它赋值
         * 当结束事务时,需要给它赋值为null
         * 并且在开启事务时,让dao的多个方法共享这个Connection
         */
        private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
        
        public static DataSource getDataSource() {
            return ds;
        }
        
        /**
         * dao使用本方法来获取连接
         * @return
         * @throws SQLException
         */
        public static Connection getConnection() throws SQLException {
            /*
             * 如果有事务,返回当前事务的con
             * 如果没有事务,通过连接池返回新的con
             */
            Connection con = tl.get();//获取当前线程的事务连接
            if(con != null) return con;
            return ds.getConnection();
        }
        
        /**
         * 开启事务
         * @throws SQLException 
         */
        public static void beginTransaction() throws SQLException {
            Connection con = tl.get();//获取当前线程的事务连接
            if(con != null) throw new SQLException("已经开启了事务,不能重复开启!");
            con = ds.getConnection();//给con赋值,表示开启了事务
            con.setAutoCommit(false);//设置为手动提交
            tl.set(con);//把当前事务连接放到tl中
        }
        
        /**
         * 提交事务
         * @throws SQLException 
         */
        public static void commitTransaction() throws SQLException {
            Connection con = tl.get();//获取当前线程的事务连接
            if(con == null) throw new SQLException("没有事务不能提交!");
            con.commit();//提交事务
            con.close();//关闭连接
            con = null;//表示事务结束!
            tl.remove();
        }
        
        /**
         * 回滚事务
         * @throws SQLException 
         */
        public static void rollbackTransaction() throws SQLException {
            Connection con = tl.get();//获取当前线程的事务连接
            if(con == null) throw new SQLException("没有事务不能回滚!");
            con.rollback();
            con.close();
            con = null;
            tl.remove();
        }
        
        /**
         * 释放Connection
         * @param con
         * @throws SQLException 
         */
        public static void releaseConnection(Connection connection) throws SQLException {
            Connection con = tl.get();//获取当前线程的事务连接
            if(connection != con) {//如果参数连接,与当前事务连接不同,说明这个连接不是当前事务,可以关闭!
                if(connection != null &&!connection.isClosed()) {//如果参数连接没有关闭,关闭之!
                    connection.close();
                }
            }
        }
    }
    JdbcUtils

    DBUtils类

    C3P0是连接池类,主要目的是获得Connection对象,

    而DButils类需要一个Connection对象,对ResultSet中的数据操作进行了转换和简化。

    你现在可以把ResultSet中数据放到一个List中,或者Map中,或者一个bean中

    DBUtils主要是QueryRunner类

    update为例子

    update函数原型

    public int update(Connection con ,String sql);

    public int update(Connection con,String sql,Object...params);//为了传入PreparedStatement 数量不一的?形式的参数

    String sql="insert into user values(?,?,?)";

    QueryRunner qr=new QueryRunner(con);

    qr.update(sql,"23","sam","123");

    con.close();

    query为例子

    在DAO模式下,有类Customer属性分别是String id,String name,String date

    数据库表t_customer分别对应。

    public <T> T query(Connection,String sql,ResultSetHandler<T> rsh)或者

    public <T> T query(Connection,String sql,ResultSetHandler<T> rsh,Object...params)

    接口ResultSetHandler有很多不同形式的实现,方便 返回不同的数据类型。

    例1.返回所有

    String sql="select * from t_customer";

    返回Customer对象的列表。BeanListHandler<T>实现的是ResultSetHandler<List<T>>

    构造函数为public BeanListHandler(Class<T> type),参数为bean的Class类型,这里传入Customer.class

    public List<Customer> findAll(){

      QueryRunner qr=new QueryRunner(con);

      String sql="select * from t_customer";

      return qr.query(sql,newBeanListHandler<Customer>(Customer,class));

    }

    例2,返回id为XX的一个对象

    public Customer load(String cid){

      QueryRunner qr=new QueryRunner(con);

      String sql="select * from t_customer where cid=?";

      return qr.query(sql,new BeanHandler<Customer>(Customer.class));

    }

    其他实现举例
    MapHandler 将结果转成Map<String,Object>其中键就是数据表的列

    MapListHandler结果转成List<Map<String,Object>,

    ColumnListHandler转成List<Object>,需要指定列的名字,new ColumnListHandler("name");

    ScalarHandler用于集聚查询,select count(*) from tableXXX;

    在代码中的使用:除了第三个,直接传入一个new的对象。

  • 相关阅读:
    无法识别的属性“targetFramework”。请注意属性名称区分大写和小写。错误解决的方法
    OpenGL 4 : 一个漂亮的心 For you, My Love
    request.getParameterValues与request.getParameter的差别
    Mac下搭建quick cocos2d-x编译环境
    【Github教程】史上最全github用法:github入门到精通
    OSI七层模型具体解释
    Android Service 服务(一)—— Service
    几种更新(Update语句)查询的方法
    epoll使用具体解释(精髓)
    SSL连接建立过程分析(1)
  • 原文地址:https://www.cnblogs.com/legion/p/9376620.html
Copyright © 2011-2022 走看看