Scala 之 mysql 数据库连接池

来源:互联网 发布:淘宝网首页官网电脑版 编辑:程序博客网 时间:2024/06/08 02:59

转子:http://blog.csdn.net/weinierzui/article/details/72867329


看到有大神用sparkstreaming里面的MongoDB 创建的工具类,好像很厉害,但是现在还不太懂。
推荐:在Spark中通过Scala + Mongodb实现连接池       也可参考spark官网

存在问题:无法将spark产生的dataframe数据用这种方式,存放到数据库中。????????????


数据库操作方法:
jdbcUtile  类
dataframe.write.jdbc

数据库连接池:
MongoDB
自己写连接池




一下工具类,只要修改数据库连接参数就可使用,本人使用的是properties配置文件读取的稍有出入,代码奉上:
var prd:PreparedStatement = null  val props = getProperties() private var current_num = 0      //当前连接池已产生的连接数  private val max_connection = props.getProperty("orc.max_connection")     //最大连接数  private val connection_num = props.getProperty("orc.init_connection_num") //初始化产生连接数  private val pools = new LinkedList[Connection]()   //连接池  private val driver = props.getProperty("driver")  private val url = props.getProperty("url")  private  val user = props.getProperty("user")  private val pwd = props.getProperty("password")
获取配置文件的工具方法:
def getProperties(): Properties ={    val props = new Properties()    val in=this.getClass.getClassLoader.getResourceAsStream("dbconfig.properties")    props.load(in)    props  }

scala数据库工具类

scala的数据库连接池,基于mysql

复制代码
import java.util.concurrent.ConcurrentHashMapimport com.jolbox.bonecp.{ BoneCPConfig, BoneCP }import java.util.ResourceBundleimport java.util.LinkedListimport java.sql.DriverManagerimport java.sql.Connection/** * 数据库连接池工具类 * 语言:scala * 时间:2016-07-09 */object DBConnectionPool {  private val reader = ResourceBundle.getBundle("connection")  private val max_connection = reader.getString("jeecg.max_connection") //连接池总数  private val connection_num = reader.getString("jeecg.connection_num") //产生连接数  private var current_num = 0 //当前连接池已产生的连接数  private val pools = new LinkedList[Connection]() //连接池  private val driver = reader.getString("jeecg.driver")  private val url = reader.getString("jeecg.url")  private val username = reader.getString("jeecg.username")  private val password = reader.getString("jeecg.password") /**  * 加载驱动  */  private def before() {    if (current_num > max_connection.toInt && pools.isEmpty()) {      print("busyness")      Thread.sleep(2000)      before()    } else {      Class.forName(driver)    }  }  /**   * 获得连接   */  private def initConn(): Connection = {    val conn = DriverManager.getConnection(url, username, password)    conn  }  /**   * 初始化连接池   */  private def initConnectionPool(): LinkedList[Connection] = {    AnyRef.synchronized({      if (pools.isEmpty()) {        before()        for (i <- 1 to connection_num.toInt) {          pools.push(initConn())          current_num += 1        }      }      pools    })  }  /**   * 获得连接   */  def getConn():Connection={     initConnectionPool()     pools.poll()  }  /**   * 释放连接   */  def releaseCon(con:Connection){    pools.push(con)  }  }
复制代码

配置文件

复制代码
#数据库连接池配置文件jeecg.driver=org.gjt.mm.mysql.Driverjeecg.url=jdbc\:mysql\://0.0.0.0\:3306/jeecg?useUnicode=true&characterEncoding=utf-8jeecg.username=rootjeecg.password=****jeecg.max_connection=8jeecg.connection_num=10
复制代码

dao类

复制代码
import java.sql.ResultSetimport java.sql.PreparedStatementimport java.sql.Connectionimport java.sql.Statement/** * 数据操作工具类 * 语言:scala * 时间:2016-07-09 */private[org] abstract class BaseDao[T](conn: Connection) {  /**   * 插入数据   * @param sql SQL语句   * @param params 参数列表   * @param convert 主键转换方法   * @return 转换结果   */  protected def insert[T](sql: String, params: Array[Any])(convert: ResultSet => T) = {    val pstmt = conn prepareStatement (sql, Statement.RETURN_GENERATED_KEYS)    setParameters(pstmt, params)    pstmt.executeUpdate    val rs = pstmt.getGeneratedKeys    rs.next    convert(rs)  }  /**   * 更新数据   * @param sql SQL语句   * @param params 参数列表   * @return 影响行数   */  protected def update(sql: String, params: Array[Any]) = createStatement(sql, params).executeUpdate  /**   * 查询对象   * @param sql SQL语句   * @param params 参数列表   * @param convert 结果集转换方法   * @return 泛型对象   */  protected def queryForObject[T](sql: String, params: Array[Any])(convert: ResultSet => T) = {    val rs = query(sql, params)    if (rs.next) {      val result = convert(rs)      if (rs.next) {        val ex = new ResultsTooManyException        throw ex      } else Some(result)    } else None  }  /**   * 查询对象列表   * @param sql SQL语句   * @param params 参数列表   * @param convert 结果集转换方法   * @return 泛型对象列表   */  protected def queryForList[T](sql: String, params: Array[Any])(convert: ResultSet => T) = {    val rs = query(sql, params)    var results = List[T]()    while (rs.next) { results = results :+ convert(rs) }    results  }  /**   * 查询对象映射   * @param sql SQL语句   * @param params 参数列表   * @param convert 结果集转换方法   * @return 泛型对象映射   */  protected def queryForMap[K, V](sql: String, params: Array[Any])(convert: ResultSet => (K, V)) = {    val rs = query(sql, params)    var results = Map[K, V]()    while (rs.next) { results += convert(rs) }    results  }  /**   * 查询   * @param sql SQL语句   * @param params 参数列表   */  private def query(sql: String, params: Array[Any]) = createStatement(sql, params).executeQuery  /**   * 创建声明   * @param sql SQL语句   * @param params 参数列表   */  private def createStatement(sql: String, params: Array[Any]) = {    val pstmt = conn prepareStatement sql    setParameters(pstmt, params)    pstmt  }  /**   * 插入参数   * @param pstmt 预编译声明   * @param params 参数列表   */  private def setParameters(pstmt: PreparedStatement, params: Array[Any]) {    for (i <- 1 to params.length) { pstmt setObject (i, params(i - 1)) }  }}/** * 结果值读取器 */object ResultValueGetter {  /**   * 查询结果值   * @param rs 结果集   * @param getResult 获得单个值结果的方法   * @return 值   */  def getResultValue[T](rs: ResultSet)(getResult: ResultSet => T) = {    val result = getResult(rs)    if (rs.wasNull) None else Some(result)  }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colNum 列号   */  def getStringValue(rs: ResultSet, colNum: Int) = getResultValue(rs) { _ getString colNum }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colNum 列号   */  def getIntValue(rs: ResultSet, colNum: Int) = getResultValue(rs) { _ getInt colNum }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colNum 列号   */  def getLongValue(rs: ResultSet, colNum: Int) = getResultValue(rs) { _ getLong colNum }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colNum 列号   */  def getDoubleValue(rs: ResultSet, colNum: Int) = getResultValue(rs) { _ getDouble colNum }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colNum 列号   */  def getBooleanValue(rs: ResultSet, colNum: Int) = getResultValue(rs) { _ getBoolean colNum }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colNum 列号   */  def getTimestampValue(rs: ResultSet, colNum: Int) = getResultValue(rs) { _ getTimestamp colNum }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colName 列名   */  def getStringValue(rs: ResultSet, colName: String) = getResultValue(rs) { _ getString colName }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colName 列名   */  def getIntValue(rs: ResultSet, colName: String) = getResultValue(rs) { _ getInt colName }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colName 列名   */  def getLongValue(rs: ResultSet, colName: String) = getResultValue(rs) { _ getLong colName }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colName 列名   */  def getDoubleValue(rs: ResultSet, colName: String) = getResultValue(rs) { _ getDouble colName }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colName 列名   */  def getBooleanValue(rs: ResultSet, colName: String) = getResultValue(rs) { _ getBoolean colName }  /**   * 获得字符串结果的值   * @param rs 结果集   * @param colName 列名   */  def getTimestampValue(rs: ResultSet, colName: String) = getResultValue(rs) { _ getTimestamp colName }}/** * 结果太多异常 */class ResultsTooManyException extends Exception("Returned too many results.") {}
复制代码


附加两外一篇博文:http://www.thebigdata.cn/JieJueFangAn/30366.html

在Spark Streaming的应用程序中,有时候需要将计算结果保存到数据库中,为了高效这里使用批量插入,结合c3po连接池,说明一下使用方法。

  1. 数据计算完成后,在foreachRDD中批量插入数据,因为是针对每一个partiton的数据操作,所以使用 rdd.foreachPartition,这里是一个批量插入页面PV和UV的操作,代码如下

    //RDD[(String,Int,Int)] 的意思是RDD[(页面名称,UV,PV)]data.foreachRDD((rdd:RDD[(String,Int,Int)],time:Time)=>{   rdd.foreachPartition(data=>{     //从连接池中获取一个连接     val conn = MDBManager.getMDBManager(isLocal).getConnection     conn.setAutoCommit(false)     val sql = "insert into tableName set pageName=?,uvNum=?,pvNum=?"     val preparedStatement = conn.prepareStatement(sql)     data.foreach(r => {       preparedStatement.setObject(1, r._1)       preparedStatement.setObject(2, r._2)       preparedStatement.setObject(3, r._3)       preparedStatement.addBatch()     })   //批量提交,如果数据量大,这里可以分批提交     preparedStatement.executeBatch()     conn.commit()     conn.close()})
  2. 这里创建一个单例的MDBManager,并使用c3p0获取连接,代码如下

    class MDBManager(isLocal:Boolean) extends Serializable{             private val cpds: ComboPooledDataSource = new ComboPooledDataSource(true); private val prop = new Properties() private var in:InputStream = _     isLocal match{     case true  => in = getClass().getResourceAsStream("/c3p0.properties");     case false => in = new FileInputStream(new File(SparkFiles.get("c3p0.properties")))  }        try {   prop.load(in);   cpds.setJdbcUrl(prop.getProperty("jdbcUrl").toString());   cpds.setDriverClass(prop.getProperty("driverClass").toString());   cpds.setUser(prop.getProperty("user").toString());   cpds.setPassword(prop.getProperty("password").toString());      cpds.setMaxPoolSize(Integer.valueOf(prop.getProperty("maxPoolSize").toString()));      cpds.setMinPoolSize(Integer.valueOf(prop.getProperty("minPoolSize").toString()));      cpds.setAcquireIncrement(Integer.valueOf(prop.getProperty("acquireIncrement").toString()));      cpds.setInitialPoolSize(Integer.valueOf(prop.getProperty("initialPoolSize").toString()));      cpds.setMaxIdleTime(Integer.valueOf(prop.getProperty("maxIdleTime").toString())); } catch {   case ex: Exception => ex.printStackTrace() } def getConnection:Connection={       try {           return cpds.getConnection();       } catch {        case ex:Exception => ex.printStackTrace()       null     }   }   }object MDBManager{  var mdbManager:MDBManager=_def getMDBManager(isLocal:Boolean):MDBManager={   synchronized{       if(mdbManager==null){           mdbManager = new MDBManager(isLocal)       }   }   mdbManager }}

    因为本地模式和集群模式的不同获取c3p0.properties配置文件也不一样,代码中分别提供了两种获取配件文件的方式,通过参数isLocal来确定使用哪种方式。

  3. 由于使用的是mysql数据库和c3p0连接池,所以提交应用时需要添加mysql连接的jar包和c3p0的jar包,在Spark-submit中添加参数

    --jars /usr/local/spark1.3/lib/mysql-connector-java-5.1.38-bin.jar,/usr/local/spark1.3/lib/c3p0-0.9.1.2.jar
  4. 提交应用时添加c3p0的配置文件,在Spark-submit中添加参数
    --files /usr/local/spark1.3/conf/c3p0.properties



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小区楼宇门坏了怎么办 门的锁坏了怎么办 汽车门把锁坏了怎么办 厨柜门上的板板掉了怎么办 衣柜门滑轮坏了怎么办 厨房推拉门推动时有声音是怎么办? 塑料推拉门声音大怎么办不好推 推拉门锁扣坏了怎么办 衣柜移门拉不动怎么办?如何保养 擦黑色桌面有层白灰怎么办 宝宝睡觉不盖被子怎么办 孩子盖被子就哭怎么办 一盖被子就发烧怎么办 两岁宝宝认被子盖怎么办 小孩吃多了发烧怎么办 两岁宝宝拉蛔虫怎么办 吃了长蛆的东西怎么办 被蜱虫咬了又找不到虫子怎么办 木家具生黑虫子怎么办 吃了发霉的面包怎么办 种的韭菜有蛆怎么办 活狗身上长蛆虫怎么办 狗身上会有蛆虫怎么办 狗身上长满了蛆怎么办 房间墙上有很多小虫子怎么办 床上有许多小虫子怎么办? 店里有许多小虫子怎么办 房间潮湿有很多小虫子怎么办 家里潮湿墙上发霉长小虫怎么办? 房间有小飞虫子怎么办 狗被灭虫剂喷了怎么办 吃鸡玩久了手机屏幕很涩怎么办 超东卧室太阳晒怎么办 床头上的布破了怎么办 老年机全静音了怎么办 老年机手机不亮怎么办 70岁老人耳朵聋怎么办 血压太低了头晕怎么办 血压高忽然变低怎么办 血压高眼睛红了怎么办 高血压200降不下去.怎么办