天天看点

JNDI连接数据库

一、jndi数据库连接通用数据访问层(jndidbmanager)

代码下:

package com.myphome.dao;

import java.sql.connection;

import java.sql.preparedstatement;

import java.sql.resultset;

import java.sql.sqlexception;

import java.util.arraylist;

import java.util.list;

import javax.naming.context;

import javax.naming.initialcontext;

import javax.naming.namingexception;

import javax.sql.datasource;

/**

 * jndi数据库连接通用数据访问层

 * */

public class jndidbmanager {

 //mysql连接固定参数和数据源名称字符串(分为两部分"java:comp/env"为javaee默认路径,"jdbc/blog"为datasource名)

 private static final string mysql_datasource_string="java:comp/env/jdbc/blog";

 //sqlserver连接固定参数和数据源名称字符串

 private static final string sqlserver_datasource_string="java:comp/env/googlesnack";

 //oracle连接固定参数和数据源名称字符串

 private static final string oracle_datasource_string="java:comp/env/users";

 //使用单例模式来保存数据库对象

 private static threadlocal<connection> tlconn=new threadlocal<connection>();

 /**

  * 获取jndi连接数据库对象

  * @throws namingexception

  * @throws sqlexception

  * */

 public connection getconnection() throws namingexception, sqlexception{

 /*

  * threadlocal类可以保存一个对象,只能保存一个, 调用get方法得到保存的对象, 调用set方法向threadlocal中保存对象

  * 调用remove()方法,将threadlocal中的对象移除

  * 如果threadlocal中保存了连接对象,就从threadlocal中获取连接对象

  * 如果threadlocal没有保存连接对象,就从连接池中获取一个连接对象,并把该连接对象保存到threadlocal中

  */

  //从threadlocal获取connection对象

  connection conn=tlconn.get();

  //如果threadlocal中存在连接对象,则返回连接对象

  if(conn!=null){

   return conn;

  }else{

  //否则从连接池中获取一个连接对象,然后将连接对象放到threadlocal中,并返回该连接对象

   //数据源datasource由tomcat提供,不能在程序中创建实例,并使用jndi获得datasource引用

   /*

    *jndi(java naming and directory interface,java命名和目录接口)是一组在java应用中访问命名和目录服务的api

    *javax.namming.context接口的lookup()方法

    */

   context context=new initialcontext();

    *javax.sql.datasource接口负责建立与数据库的连接

    *从tomcat的数据源获得连接

    *把连接保存在连接池中

   //mysql

   datasource ds=(datasource) context.lookup(mysql_datasource_string);

   //sqlserver

//   datasource ds=(datasource) context.lookup(sqlserver_datasource_string);

//   //oracle

//   datasource ds=(datasource) context.lookup(oracle_datasource_string);

   //获取连接对象

   conn=ds.getconnection();

   //将数据库连接对象放入到threadlocal中

   tlconn.set(conn);

  }

 }

  * 从threadlocal中移除连接对象,以免线程池误操作本地变量

 public void removeconnection()throws exception {

  tlconn.remove();//将threadlocal中保存的连接对象移除,移除后tl.get()方法得到的结果是null

  * 为sql语句占位符赋值

 private void operateparameters(preparedstatement pstmt,object ... args) throws sqlexception {

    if (args != null && args.length > 0) {

        for (int i = 0; i < args.length; i++) {

            pstmt.setobject(i + 1, args[i]);

        }

   }

  * 将结果集转换为实体对象的接口

  * mapper接口用于规定将数据行转换为entity的方法,以mapper结尾的类(如:articlemapper)是该接口的子类

  * mapper子类用于将rs指向的数据行转换为指定的entity对象

 public static interface rowmapper<t> {

  public t rowmapper(resultset rs);

  * 数据库查询方法

  * @return list<t>

  * 第二个参数rowmapper:明确由哪个类负责将数据行转换为entity对象

  * 第一个参数:sql语句

  * 第三个参数:sql语句参数的值

 public <t> list<t> executequery(string sql, rowmapper mapper,object ... values) throws exception{

  list list = new arraylist<t>();

  connection conn = null;

  preparedstatement pstmt = null;

  resultset rs = null;

  try {

   conn = getconnection();

   pstmt = conn.preparestatement(sql);

   operateparameters(pstmt, values);

   rs = pstmt.executequery();

   //将结果集一条记录转换为实体对象,并添加到集合中

   while (rs.next()) {

    t obj = (t) mapper.rowmapper(rs);

    list.add(obj);

   }

  } catch (sqlexception e) {

   e.printstacktrace();

   throw new exception("执行数据查询时,失败");

  } finally {

   //关闭rs

   closeresultset(rs);

   //关闭pstmt

   closestatement(pstmt);

   //注意,rs和pstmt是dbmanager关闭的,conn是有调用dbmanager类关闭的

  return list;

  * 数据库更新数据方法(添加、修改、删除)

  * @return int

 public int executeupdate(string sql, object...args) throws exception {

  int rowcount = 0;

  connection conn = getconnection();

   operateparameters(pstmt, args);

   rowcount = pstmt.executeupdate();

   throw new exception("更新数据失败");

  return rowcount;

  * 执行聚合函数查询(求总和)

 public int executescalar(string sql,object ...values){

   if(rs.next()){

    return rs.getint(1);

   return 0;

  }catch (exception e) {

  }finally{

  * 关闭连接

  *

  * @param dbconnection

  *            connection

 public void closeconnection() {

   connection conn = tlconn.get();

   if (conn != null && (!conn.isclosed())) {

    //关闭连接对象

    conn.close();

    conn = null;

    //将连接对象从tl中移除

    tlconn.remove();

  * 关闭结果集

 public void closeresultset(resultset rs) {

   if (rs != null) {

    rs.close();

    rs = null;

  * 关闭语句

 public void closestatement(preparedstatement pstmt) {

   if (pstmt != null) {

    pstmt.close();

    pstmt = null;

  * 开始事务

 public void setautocommit()throws exception {

   getconnection();

   //开始事务

   tlconn.get().setautocommit(false);

   throw new exception("开始事务时,出现错误");

  * 提交事务

 public void commit() throws exception {

   //提交事务

   tlconn.get().commit();

   throw new exception("事务提交失败");

  * 回滚事务

 public void rollback() throws exception{

   //回滚事务

   tlconn.get().rollback();

   throw new exception("事务回滚失败");

}

二、将结果集rs指向的数据当前一行记录转换为指定的entity对象的mapper类(如:foodmapper)

package com.myphome.mapper;

import com.myphome.dao.jndidbmanager;

import com.myphome.entity.food;

 *foodmapper用于将界面需要的数据查询出来,然后将rs指向的一条记录转换为food实体类

 */

public class foodmapper implements

jndidbmanager.rowmapper<food> {

 public food rowmapper(resultset rs) {

  food food = null;

   food = new food();

   food.setagio(rs.getdouble("agio"));

   food.setcharacteristics(rs.getstring("characteristics"));

   food.setcuisine(null);//把其他实体类作为此对象属性赋值(用第二个sql查询赋值,即sql嵌套)

   food.setcuisineid(rs.getint("cuisineid"));

   food.seteatery(null);

   food.seteateryid(rs.getint("eateryid"));

   food.setfingredient(rs.getstring("fingredient"));

   food.setid(rs.getint("id"));

   food.setimg(rs.getstring("img"));

   food.setintegral(rs.getint("integral"));

   food.setname(rs.getstring("name"));

   food.setprice(rs.getdouble("price"));

   food.setremark(rs.getstring("remark"));

  } catch (exception e) {

   food =null;

  return food;

三、food实体类

package com.myphome.entity;

import java.io.serializable;

 * 菜品

public class food implements serializable{

 private int id; //食物的主键

 private string name;//食物的名称

 private string fingredient;//食物的配料

 private double price;//食物的价格

 private double agio;//食物的折扣

 private string remark;//食物的简介

 private string characteristics;//食物的特色

 private string img;//食物的图片

 private int integral;//购买食物所送积分

 private int cuisineid;//食物所属菜系的id

 private int eateryid;//食物所属餐馆的id

 //对象属性,菜系类

 private cuisine cuisine;

 //对象属性,菜馆类

 private eatery eatery;

 public int getid() {

  return id;

 public void setid(int id) {

  this.id = id;

 public string getname() {

  return name;

 public void setname(string name) {

  this.name = name;

  * 获取配料

 public string getfingredient() {

  return fingredient;

  * 设置配料

 public void setfingredient(string fingredient) {

  this.fingredient = fingredient;

 public double getprice() {

  return price;

 public void setprice(double price) {

  this.price = price;

 public double getagio() {

  return agio;

 public void setagio(double agio) {

  this.agio = agio;

 public string getremark() {

  return remark;

 public void setremark(string remark) {

  this.remark = remark;

  * 获取特色

 public string getcharacteristics() {

  return characteristics;

  * 设置特色

 public void setcharacteristics(string characteristics) {

  this.characteristics = characteristics;

 public string getimg() {

  return img;

 public void setimg(string img) {

  this.img = img;

  * 获取积分

 public int getintegral() {

  return integral;

  * 设置积分

 public void setintegral(int integral) {

  this.integral = integral;

 public int getcuisineid() {

  return cuisineid;

 public void setcuisineid(int cuisineid) {

  this.cuisineid = cuisineid;

 public int geteateryid() {

  return eateryid;

 public void seteateryid(int eateryid) {

  this.eateryid = eateryid;

 public cuisine getcuisine() {

  return cuisine;

 public void setcuisine(cuisine cuisine) {

  this.cuisine = cuisine;

 public eatery geteatery() {

  return eatery;

 public void seteatery(eatery eatery) {

  this.eatery = eatery;

四、jndi的配置步骤:

1.tomcat的conf/context.xml中的配置:

<context>

 <!--**jndi  datasource数据源tomcat下配置**-->

 <!--sqlserver-->

 <resource name="googlesnack" auth="container" type="javax.sql.datasource"

    maxactive="100" maxidle="30" maxwait="10000"

    username="sa" password="sa" driverclassname="com.microsoft.jdbc.sqlserver.sqlserverdriver"

    url="jdbc:sqlserver://localhost:1433;databasename=google_snack"/>

 <!--mysql-->

 <resource name="jdbc/blog" auth="container" type="javax.sql.datasource"

  maxactive="100" maxidle="30" maxwait="60000"

  username="root" password="root" driverclassname="org.gjt.mm.mysql.driver"

  url="jdbc:mysql://localhost:3306/blog"/>

 <!--oracle-->

 <resource name="users" auth="container" type="javax.sql.datasource"

  username="kekeai" password="kekeai123" driverclassname="oracle.jdbc.driver.oracledriver"

  url="jdbc:oracle:thin:@localhost:1521:orcl"/>

</context>

  注:

JNDI连接数据库

2.加入数据库驱动文件:

把数据库驱动的.jar文件,加入到tomcat下的lib中。

3.(可省略)应用程序的web.xml文件的配置,在web.xml中配置<resource-ref>:

JNDI连接数据库

注:如果用junit测试,将报错:

javax.naming.noinitialcontextexception: need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial

解决:用web项目形式测试,则成功!

//tomcat下context.xml 中有汉字将报编码错误。

//界面提交using post method,则:this.dopost(request,response);