JNDI连接数据库

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 一、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);

 

 

 

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
28天前
|
SQL 关系型数据库 MySQL
2024年阿里云数据库创建_数据库账号密码和连接教程
阿里云数据库怎么使用?阿里云百科整理阿里云数据库从购买到使用全流程,阿里云支持MySQL、SQL Server、PostgreSQL和MariaDB等数据库引擎,阿里云数据库具有高可用、高容灾特性,阿里云提供数据库备份、恢复、迁移全套解决方案。详细阿里云数据库购买和使用流程方法如下
|
1月前
|
数据采集 Java 关系型数据库
Java代码高效连接数据库
Java代码高效连接数据库
15 2
|
1月前
|
Ubuntu 关系型数据库 MySQL
【MySQL】Navicat/SQLyog连接Ubuntu中的数据库(MySQL)
【MySQL】Navicat/SQLyog连接Ubuntu中的数据库(MySQL)
|
24天前
|
SQL 关系型数据库 MySQL
阿里云MySQL数据库价格、购买、创建账号密码和连接数据库教程
阿里云数据库使用指南:购买MySQL、SQL Server等RDS实例,选择配置和地区,完成支付。创建数据库和账号,设置权限。通过DMS登录数据库,使用账号密码访问。同地域VPC内的ECS需将IP加入白名单以实现内网连接。参考链接提供详细步骤。
364 3
|
1月前
|
SQL 关系型数据库 MySQL
用 Python 连接数据库并进行查询。
【2月更文挑战第12天】【2月更文挑战第32篇】用 Python 连接数据库并进行查询。
|
1天前
|
JavaScript 关系型数据库 MySQL
❤Nodejs 第二章(Node连接本地数据库)
【4月更文挑战第2天】本文介绍了如何使用Node.js连接本地MySQL数据库。首先,提到了在MySQL官网下载安装数据库和使用Navicat for MySQL进行数据库管理。接着,通过`yarn add mysql`在项目中安装数据库依赖。然后,创建`app.js`文件,设置数据库连接参数,并建立连接进行查询操作。遇到导入模块的错误后,修改导入方式为CommonJS语法。
10 1
|
4天前
|
SQL 监控 关系型数据库
PG数据库释放闲置连接
PG数据库释放闲置连接
8 0
|
13天前
|
弹性计算 关系型数据库 MySQL
阿里云数据库服务器价格表,数据库创建、连接和使用教程
阿里云数据库使用流程包括购买和管理。选择所需数据库类型如MySQL,完成实名认证后购买,配置CPU、内存和存储。确保数据库地域与ECS相同以允许内网连接。创建数据库和账号,设置权限。通过DMS登录数据库,使用账号密码连接。同一VPC内的ECS需添加至白名单以进行内网通信。参考官方文档进行详细操作。
71 3
|
15天前
|
网络协议 数据库连接 网络安全
DM数据库连接数据库时报:创建sokect连接失败
DM数据库连接数据库时报:创建sokect连接失败
12 0
|
1月前
|
SQL 关系型数据库 MySQL
阿里云数据库使用方法,从购买、创建数据库账号密码到连接数据库全流程
阿里云数据库使用方法,从购买、创建数据库账号密码到连接数据库全流程,阿里云数据库怎么使用?阿里云百科整理阿里云数据库从购买到使用全流程,阿里云支持MySQL、SQL Server、PostgreSQL和MariaDB等数据库引擎,阿里云数据库具有高可用、高容灾特性,阿里云提供数据库备份、恢复、迁移全套解决方案
326 0

热门文章

最新文章