开发者社区> tony~tian> 正文

JNDI连接数据库

简介: 一、JNDI数据库连接通用数据访问层(JNDIDBManager) 代码下: package com.myphome.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; impor
+关注继续查看

一、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.Tomcatconf/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);

 

 

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java JDBC连接数据库
桥连:sun.jdbc.odbc.JdbcOdbcDriver 连接字符串:("jdbc:odbc:数据源名","sa","sa"); 纯Java驱动:com.microsoft.jdbc.sqlserver.SQLServerDriver 连接字符串: ("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=数据库名","
1566 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
28396 0
详解JDBC连接数据库
一、概念   1. 为了能让程序操作数据库,对数据库中的表进行操作,每一种数据库都会提供一套连接和操作该数据库的驱动,而且每种数据库的驱动都各不相同,例如mysql数据库使用mysql驱动,oracle数据库使用oracle驱动,这样假如我们编写的程序哪一天想要换数据库,那样就会很不方便,因为所有连接数据库的代码都要从新编写。
958 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
20320 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
23543 0
云数据库的连接
大家好,小编整理了关于如何简单登录阿里云数据库的步骤,请看官参考
2083 0
数据库连接池
数据库连接池是一组连接集合,一般在应用启动时完成连接创建,减少查询场景发生时创建数据库连接的时间消耗。 一个连接池组件至少需要完成连接创建和收回,实现过程中往一个数组中放入创建完成的连接,用时从数组取出,数据元素减1,用完放回,数据元素加1。
1149 0
JNDI连接数据库
一、JNDI数据库连接通用数据访问层(JNDIDBManager) 代码下: package com.myphome.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; impor
1702 0
+关注
tony~tian
追求完美,追求自由!
122
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载