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);
   return 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 {
  PreparedStatement pstmt = null;
  int rowCount = 0;
  Connection conn = getConnection();
  try {
   pstmt = conn.prepareStatement(sql);
   operateParameters(pstmt, args);
   rowCount = pstmt.executeUpdate();
  } catch (SQLException e) {
   e.printStackTrace();
   throw new Exception("更新数据失败");
  } finally {
   closeStatement(pstmt);
  }
  return rowCount;
 }
 /**
  * 执行聚合函数查询(求总和)
  * */
 public int executeScalar(String sql,Object ...values){
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConnection();
   pstmt = conn.prepareStatement(sql);
   operateParameters(pstmt, values);
   rs = pstmt.executeQuery();
   if(rs.next()){
    return rs.getInt(1);
   }
   return 0;
  }catch (Exception e) {
   return 0;
  }finally{
   closeResultSet(rs);
   closeStatement(pstmt);
  }
 }
 /**
  * 关闭连接
  *
  * @param dbConnection
  *            Connection
  */
 public void closeConnection() {
  try {
   Connection conn = tlconn.get();
   if (conn != null && (!conn.isClosed())) {
    //关闭连接对象
    conn.close();
    conn = null;
    //将连接对象从tl中移除
    tlconn.remove();
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }

 }
 /**
  * 关闭结果集
  */
 public void closeResultSet(ResultSet rs) {
  try {
   if (rs != null) {
    rs.close();
    rs = null;
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

 /**
  * 关闭语句
  */
 public void closeStatement(PreparedStatement pstmt) {
  try {
   if (pstmt != null) {
    pstmt.close();
    pstmt = null;
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }
 /**
  * 开始事务
  * */
 public void setAutoCommit()throws Exception {
  try {
   getConnection();
   
   //开始事务
   tlconn.get().setAutoCommit(false);
  } catch (SQLException e) {
   e.printStackTrace();
   throw new Exception("开始事务时,出现错误");
  }
 }
 /**
  * 提交事务
  * */
 public void commit() throws Exception {
  try {
   //提交事务
   tlconn.get().commit();
  } catch (SQLException e) {
   e.printStackTrace();
   throw new Exception("事务提交失败");
  }
 }
 /**
  * 回滚事务
  * */
 public void rollback() throws Exception{
  try {
   //回滚事务
   tlconn.get().rollback();
  } catch (SQLException e) {
   e.printStackTrace();
   throw new Exception("事务回滚失败");
  }
 }
}

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

package com.myphome.mapper;
import java.sql.ResultSet;

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;
  try {
   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;
   e.printStackTrace();
  }
  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"
  maxActive="100" maxIdle="30" maxWait="60000"
  username="kekeai" password="kekeai123" driverClassName="oracle.jdbc.driver.OracleDriver"
  url="jdbc:oracle:thin:@localhost:1521:orcl"/>
</Context>

  注:

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

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

 

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

 

注:如果用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);

 

 

 

时间: 2024-09-20 11:58:32

JNDI连接数据库的相关文章

JNDI简介,jndi在tomcat中的配置,jdbc api简介,java连接数据库服务

连接数据库 JNDI(Java 命名和目录接口)   JNDI(Java 命名和目录接口) 分布式计算环境通常使用命名和目录服务来获取共享的组件和资源.命名和目录服务将名称与位置.服务.信息和资源关联起来.  命名服务提供名称-对象的映射.目录服务提供有关对象的信息,并提供定位这些对象所需的搜索工具.有许多命名和目录服务实现,并且到它们的接口是不同的. Java 命名和目录接口或 JNDI 提供了一个用于访问不同的命名和目录服务的公共接口.请参阅 URL java.sun.com/product

jdbc-sturts2 怎么链接到数据池

问题描述 sturts2 怎么链接到数据池 我在tomcat6.0的context.xml文件里加了这个 </Context> <Context reloadable="true"> <Resource name="jdbc/ice_db" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait=&quo

[Servlet&amp;JSP] 使用JDBC连接数据库

JDBC(Java DataBase Connectivity)时用于运行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行实现,这样开发人员就可以无需接触底层数据库驱动程序的差异性. JDBC简介 厂商在实现JDBC驱动程序时,依方式可将驱动程序分为四种类型: JDBC-ODBC Bridge Driver 将JDBC调用转换为ODBC调用 Native API Driver 将JDBC调用转换为原生链接库中的相关API调用.特点:与平台相依,是四种类型中最快的驱动程序.

[Servlet&amp;amp;JSP] 使用JDBC连接数据库

JDBC(Java DataBase Connectivity)时用于运行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行实现,这样开发人员就可以无需接触底层数据库驱动程序的差异性. JDBC简介 厂商在实现JDBC驱动程序时,依方式可将驱动程序分为四种类型: JDBC-ODBC Bridge Driver 将JDBC调用转换为ODBC调用 Native API Driver 将JDBC调用转换为原生链接库中的相关API调用.特点:与平台相依,是四种类型中最快的驱动程序.

JNDI数据库连接池

JNDI的全称是java命名与目录接口(Java Naming and Directory Interface),是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用.统一的接口.我们可以把JNDI简单地理解为是一种将对象和名字绑定的技术,即指定一个资源名称,将该名称与某一资源或服务相关联,当需要访问其他组件和资源时,就需要使用JNDI服务进行定位,应用程序可以通过名字获取对应的对象或服务. JNDI方式 - 配置Tomcat6.0 连接池 数据库连接池的基本思想就是为

ibatis2.0 连接数据库对密码字段加密的问题

问题描述 问题描述:数据源在jdbc.properties文件中,现在要求对password字段进行加密保存,要求对password解密后连接数据库.现有的sqlMapConfig配置如下:<sqlMapConfig><propertiesresource="jdbc.properties"/><transactionManagertype="JDBC"commitRequired="true"><dat

spring mvc-springMVC+maven,启动报报JNDI的错误,但我没有用到JNDI

问题描述 springMVC+maven,启动报报JNDI的错误,但我没有用到JNDI 要修改一个项目,用的技术有springMVC,maven等,部署到tomcat下,启动时报错.项目中使用的连接池连接数据库,没有使用JNDI,为什么启动时老是去查找JNDI? applicationContext.xml中定义了项目的环境: location="classpath*:/application.properties" /> <!-- Tomcat JDBC连接池 -->

Tomcat使用JNDI连接MYSQL数据库

环境: jdk1.4 + Tomcat 5 一.环境变量: PATH:   C:/j2sdk1.4.2/bin; JAVA_HOME:  C:/j2sdk1.4.2/ 注:仅此两个. 二.JDBC 驱动 COPY 相应的JDBC驱动程序到Tomcat5/common/libSQL Server 2000(或mysql) for JDBC/lib/目录下三个.jar :msbase.jarmssqlserver.jarmsutil.jar  三.虚拟目录与连接池 假设要在D:/JsgTest建自己

ssh框架动态连接数据库

问题描述 请问ssh框架已经搭建好连接数据库,怎么改为自动连接数据库呢?不在配置文件里设置数据库的用户名和密码,怎么在外面设置连接数据库呢? 问题补充:sy197661944 写道 解决方案 引用正常情况下SSH框架里是有个配置文件.property文件配置数据库,如果动态连接数据库是不是就不用配置这个文件呢?spring文件里有个配置获得这个数据库的信息,如果动态连接数据库,spring里该怎么设置呢? 在spring加载这个数据文件前,先用流写一个这个文件,但是,我觉得,如果不是要让用户来配