Java JDBC拓展

Java JDBC拓展


                              上接Java JDBC来接MySql基础语法:https://mp.csdn.net/postedit/83831745 

 

(1)JDBC框架技术

①POJO:Plain Ordinary Java Object(简单Java对象)

POJO其实就是JavaBean

POJO中规定类中有:

              private成员变量(用包装类Integer、Boolean、Long、String、Double等)

              public构造方法(可以不写)

              public对应的Setter/Getter方法

说明:POJO概念的引入是为了便于对数据表中的元祖(一行数据)进行包装处理,使用包装类的原因的便于切合数据表中的NULL元素,毕竟基本数据类型是没有NULL这一说的。 

i、POJO自动reflection

 //1、根据列标题,找到对应的方法
  public static Method findMethod(Class cls, String label)
  {
    // "name" -> "setName()"

     char firstChar = Character.toUpperCase(label.charAt(0));

     StringBuffer strbuf = new StringBuffer("set" + label);

     strbuf.setCharAt(3, firstChar);

             

     // 取得对应的Method
     String methodName = strbuf.toString();

     Method[] methods = cls.getMethods();

     for (Method m : methods)

      {

          if (m.getName().equals(methodName))

          {

              return m;

           }

       }

       return null;

  }



//2、根据列标题,找到对应的方法组
 public static Method[] findMethod(Class cls, String[] labels)
 {
     Method[] methods = new Method[ labels.length ];
     
     for(int i=0; i<labels.length; i++)

     {

          methods[i] = findMethod(cls, labels[i]);

     }
     return methods;

 }



 //3、调用set方法将数据存入POJO中
  public static void map(Object pojo, Method method,

                     int columnType,

                     String columnValue) throws Exception

  {

     if(method == null) return;

     if(columnValue == null) return;

     // 根据类型,传递合适的参数给setter
      Object arg0 = null;

      if(columnType == Types.CHAR || columnType == Types.VARCHAR )

      {

          arg0 = columnValue; // 给方法传一个String参数

      }

      else if(columnType == Types.BIT) // tinyint(1)

      {

          arg0 = (columnValue.equals("1"));

       }

       else if(columnType == Types.DATE) // date

       {

           arg0 = sdf_d.parse(columnValue);

       }

       else if(columnType == Types.TIME) // time

        {

           arg0 = sdf_t.parse(columnValue);

       }

       else if(columnType == Types.TIMESTAMP) // datetime timestamp

       {

           arg0 = sdf_dt.parse(columnValue);

       }

        else if(columnType == Types.TINYINT || columnType == Types.SMALLINT

                            || columnType == Types.INTEGER || columnType == Types.BIGINT

                            || columnType == Types.DOUBLE || columnType == Types.FLOAT)

       {
             // 整数类型的处理

             Class[] parameterTypes = method.getParameterTypes();

             Class c = parameterTypes[0];

             if(c.equals( int.class) || c.equals(Integer.class))

              {

                  arg0 = Integer.valueOf(columnValue);

              }

              else if(c.equals( long.class) || c.equals(Long.class))

              {

                   arg0 =  Long.valueOf(columnValue);

              }     

              else if(c.equals( short.class) || c.equals(Short.class))

              {

                   arg0 =  Short.valueOf(columnValue);

              }

              else if(c.equals( byte.class) || c.equals(Byte.class))

              {

                    arg0 =  Byte.valueOf(columnValue);

               }

               else if(c.equals( float.class) || c.equals(Float.class))

                {

                     arg0 =  Float.valueOf(columnValue);

                }

                else if(c.equals( double.class) || c.equals(Double.class))

                {

                     arg0 =  Double.valueOf(columnValue);

                }                   

          }



     // 调用setter方法

      Object args[] = { arg0 };

       try {

             method.invoke(pojo, args);

           }catch(IllegalArgumentException e)

           {

               Class[] parameterTypes = method.getParameterTypes();

               Class c = parameterTypes[0];

           //System.out.println("期望类型:" + c.getCanonicalName() + ",
                   实际类型:" + arg0.getClass().getCanonicalName() );

          }

       说明:从数据表中将元祖信息自动映射到实体类中来。(查询数据表并读取出元祖)

 

ii、POJO手动reflection

1.XML方式映射

 

2.注解方式映射

 

说明:利用配置文件或注解的方法为了实现将实体类(具体的对象)中的数据全部写入到数据库中对应的表中,构成一行数据(元祖)。(向数据表中插入元祖)


(2)JDBC连接池

①基础知识

MySQL连接数:指客户端发起的网络连接的数量

查看最大连接数 (my.ini中设置)

       SHOW VARIABLES LIKE 'max_connections'

查看当前连接

        SHOW STATUS LIKE 'Threads%'        /* 连接数量 */

        SHOW processlist                  /* 连接详情 */

        SHOW full processlist

 

两种连接方式(短连接/长连接):

       短连接:每次都要先连接,再操作,最后关闭。(允许并发;耗费资源,效率低)

       长连接:一直建立一条连接,每次要用时直接调用这条连接,操作完后不关闭次连接供其他用户调用。(不允许并发;节省资源,效率高)

商业级数据库连接技术:连接池

       连接池:提前建立了多条连接,供用户来连接,这些连接仿佛在池子中供用户来取,当用户一时间取很多的时候,连接池中连接的个数增多,但不超过设定的最大连接数;当用户一段时间取较少的时候,连接池中连接的个数减少,但不少于设定的最小连接数。当然这其中肯定还包含很多的优化算法,这里我们就不做深层的讨论了。使用连接池可以让数据库资源使用效率高、支持并发,一般商业级的连接池采用c3p0

              C3p0官网:http://www.mchange.com/projects/c3p0/


(3)c3p0连接池技术

配置:把对应的jar包包含进eclipse中,并创建一个c3p0-config.xml文件来做默认配置      

 //c3p0-config.xml文件默认配置信息

       <?xml version="1.0" encoding="UTF-8"?>

       <c3p0-config>

     <default-config>

        <property name="driverClass">com.mysql.jdbc.Driver</property>

        <property name="jdbcUrl">jdbc:mysql://127.0.0.1/af_school</property>    

        <property name="user">root</property>

        <property name="password">a1b2c3</property>

        <property name="initialPoolSize">5</property>   <!—初始连接数 -->

        <property name="minPoolSize">2</property>    <!—最小连接数 -->

        <property name="maxPoolSize">10</property>   <!—最大连接数 -->

<!—连接的最大空闲时间,如果超过这个时间,某个数据库连接还没有被使用,则会断开掉这个连接如;果为0,则永远不会断开连接 -->

       <property name="maxIdleTime">30</property> 

      <!--池中数据连接不够时一次增长多少个-->

      <property name="acquireIncrement">5</property>

    </default-config>

</c3p0-config>



//eclipse测试

       // 一个DataSource指代一个数据源, 内部有一个连接池

       ComboPooledDataSource cpds = new ComboPooledDataSource();

       // 一个Connection代表一次访问
       Connection conn = cpds.getConnection();

       // 查询操作             
       Statement stmt = conn.createStatement();
       ResultSet rs = stmt.executeQuery("SELECT * FROM student");            

       while(rs.next())

       {
          // 取出这一行记录

           int id = rs.getInt("id");

           String name = rs.getString("name");

           String phone = rs.getString("phone"); // 可能为null

           Date birthday = rs.getDate("birthday");

           System.out.println(id + "\t" + name + "\t" + phone );           

       }   

             

      conn.close(); // 连接放回池子(并没有真正释放连接)

      cpds.close(); // 数据源如果关闭,相应的池子也就销毁了(特定时候关闭)

注:关闭连接池数据源就与普通数据库连接一样了,甚至更加耗费资源、低效


(4)防止SQL注入

SQL注入:

       sql注入是通过人为的利用sql语句,让输入的用户名或密码与代码设计的sql语句结合后构成WHERE判断永真等情况,使得个人账户信息变的及其容易破解,sql注入是数据库代码设计中必须解决的问题,有效的处理sql注入可以使得个人账户信息安全度更高,更有效的保护用户的个人隐私,防止不法分子利用个人信息或虚拟货币违法犯罪。

解决方法:引入转义符

我们知道MYSQL的sql语句中 ’ (单引号) 、` (反引号)等是种特殊字符,这种特殊字符很容易对sql语句进行改写,所以必须要处理这些特殊字符,最常见的方法就是利用转义符来是这种特殊字符成为普通字符就OK了。

       以下是利用String.replace( )方法实现特殊字符转义

       password=password.replace(" ' ", " /' ");

       password=password.replace(" ` ", " /` ");


提升篇

欢迎阅读Hibernate框架篇,Hibernate是对JDBC的优秀全自动封装。

Hibernate入门学习链接:https://blog.csdn.net/biggerchong/article/details/84229658

 

                                                                                               ------谢谢阅读!欢迎评论!    -----知飞翀

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值