*4.连接池_手写连接池_动态代理
JDBCDEMO1:
package com.itheima.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.itheima.pool.MyPool;
public class JDBCDemo1 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
MyPool pool = new MyPool();
try{
conn = pool.getConnection();
ps = conn.prepareStatement("select * from account");
rs = ps.executeQuery();
while(rs.next()){
String name = rs.getString("name");
System.out.println(name);
}
}catch (Exception e) {
e.printStackTrace();
}finally{
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
ps = null;
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}
}
}
MYPOOL:
package com.itheima.pool;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import javax.sql.DataSource;
public class MyPool implements DataSource {
private static List<Connection> pool = new LinkedList<Connection>();
static{
try{
Class.forName("com.mysql.jdbc.Driver");
for(int i=0;i<5;i++){
Connection conn = DriverManager.getConnection("jdbc:mysql:///day11","root","root");
pool.add(conn);
}
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public Connection getConnection() throws SQLException {
if(pool.size()==0){
for(int i=0;i<3;i++){
Connection conn = DriverManager.getConnection("jdbc:mysql:///day11","root","root");
pool.add(conn);
}
}
final Connection conn = pool.remove(0);
//--利用动态代理改造close方法
Connection proxy = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces()
, new InvocationHandler(){
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if("close".equals(method.getName())){
//对于想要改造的close方法,我们自己写
retConn(conn);
return null;
}else{
//对于不想改造的方法调用被代理者身上相同的方法
return method.invoke(conn, args);
}
}
});
System.out.println("获取了一个连接,池里还剩余"+pool.size()+"个连接");
return proxy;
}
private void retConn(Connection conn){
try {
if(conn!=null && !conn.isClosed()){
pool.add(conn);
System.out.println("还回了一个连接,池里还剩余"+pool.size()+"个连接");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public Connection getConnection(String username, String password)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub
}
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
}
继承&装饰:
package com.itheima.pool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface 动物{
public void 吃();
public void 叫();
}
public class 狗 implements 动物 {
public void 吃(){
System.out.println("狗在么么么么么的吃......");
}
public void 叫(){
System.out.println("狗在旺旺旺旺的叫......");
}
public static void main(String[] args) {
//狗 dog = new 继承狗();
//狗 dog = new 狗();
//动物 ani = new 装饰狗(dog);
//ani.吃();
//ani.叫();
final 狗 dog = new 狗();
动物 proxy = (动物) Proxy.newProxyInstance(狗.class.getClassLoader(), 狗.class.getInterfaces()
, new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if("叫".equals(method.getName())){
System.out.println("代理狗在哈哈哈哈的叫.....");
return null;
}else{
return method.invoke(dog, args);
}
}
});
proxy.吃();
proxy.叫();
}
}
//装饰
class 装饰狗 implements 动物{
private 动物 ani = null;
public 装饰狗(动物 ani) {
this.ani = ani;
}
public void 叫() {
System.out.println("狗在咩咩咩咩的叫.....");
}
public void 吃() {
ani.吃();
}
}
//继承
class 继承狗 extends 狗{
@Override
public void 叫() {
System.out.println("狗在喵喵喵喵的叫......");
}
}
代理:
手动写的连接池
*5.开源连接池_DBCP_C3P0
导包,两个。
开源数据源:
DBCP:
方式1:
BasicDataSource source = new BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUrl("jdbc:mysql:///day11");
source.setUsername("root");
source.setPassword("root");
方式2:
Properties prop = new Properties();
prop.load(new FileReader("dbcp.properties"));
BasicDataSourceFactory factory = new BasicDataSourceFactory();
DataSource source = factory.createDataSource(prop);
配置文件中:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day11
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
C3P0数据源:
也是先导包的,就一个,
C3P0数据源:
方式1:
ComboPooledDataSource source = new ComboPooledDataSource();
source.setDriverClass("com.mysql.jdbc.Driver");
source.setJdbcUrl("jdbc:mysql:///day11");
source.setUser("root");
source.setPassword("root");
方式2:
ComboPooledDataSource source = new ComboPooledDataSource();
在类加载目录下名称为c3p0-config.xml的配置文件中配置:
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day11</property>
<property name="user">root</property>
<property name="password">root</property>
</default-config>
</c3p0-config>
*6.开源连接池_tomcat内置连接池
tomcat内置的数据源(DBCP):
~1.如何为tomcat配置数据源
~tomcat/conf/context.xml文件中配置<Context>配置在这个位置的信息将会被所有的web应用所共享
~tomcat/conf/[engin]/[Host]/context.xml文件中可以配置<Context>标签,这里配置的信息将会被这台虚拟主机中的所有web应用所共享
~tomcat/conf/server.xml文件中的<Host>标签中配置<Context>标签,这是web应用的第一种配置方式,在这个标签中配置的信息将只对当前web应用起作用
~tomcat/conf/[engin]/[Host]/自己创建一个.xml文件,在这个文件中使用<Context>标签配置一个web应用,这是web应用第二种配置方式,在这个<Context>标签中配置的信息将只会对当前web应用起作用
~web应用还有第三种配置方式:将web应用直接放置到虚拟主机管理的目录.此时可以在web应用的META-INF文件夹下创建一个context.xml文件,在其中可以写<Context>标签进行配置,这种配置信息将只会对当前web应用起作用
<Resource name="mySource"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql:///day11"
maxActive="8"
maxIdle="4"/>
~2.如果在程序中获取这个数据源
想要访问jndi就必须在Servlet中才能执行下列代码:
Context initCtx = new InitialContext();
Context jndi = (Context) initCtx.lookup("java:comp/env");
DataSource source = jndi.lookUp("mySource");
--------------------------------------课堂笔记------------------------------
create table account (
id int primary key auto_increment,
name varchar(20),
money double
);
insert into account values(null,'a',1000),(null,'b',1000);
一、事务
事务的概念:事务是指逻辑上的一组操作,这组操作要么同时完成要么同时不完成.
事务的管理:默认情况下,数据库会自动管理事务,管理的方式是一条语句就独占一个事务.
如果需要自己控制事务也可以通过如下命令开启/提交/回滚事务
start transaction;
commit;
rollback;
JDBC中管理事务:
conn.setAutoCommit(false);
conn.commit();
conn.rollback();
SavePoint sp = conn.setSavePoint();
conn.rollback(sp);
事务的四大特性:一个事务具有的最基本的特性,一个设计良好的数据库可以帮我们保证事务具有这四大特性(ACID)
原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性:如果事务执行之前数据库是一个完整性的状态,那么事务结束后,无论事务是否执行成功,数据库仍然是一个完整性状态.
数据库的完整性状态:当一个数据库中的所有的数据都符合数据库中所定义的所有的约束,此时可以称数据库是一个完整性状态.
隔离性:事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
隔离性:
将数据库设计成单线程的数据库,可以防止所有的线程安全问题,自然就保证了隔离性.但是如果数据库设计成这样,那么效率就会极其低下.
数据库中的锁机制:
共享锁:在非Serializable隔离级别做查询不加任何锁,而在Serializable隔离级别下做的查询加共享锁,
共享锁的特点:共享锁和共享锁可以共存,但是共享锁和排他锁不能共存
排他锁:在所有隔离级别下进行增删改的操作都会加排他锁,
排他锁的特点:和任意其他锁都不能共存
如果是两个线程并发修改,一定会互相捣乱,这时必须利用锁机制防止多个线程的并发修改
如果两个线程并发查询,没有线程安全问题
如果两个线程一个修改,一个查询......
四大隔离级别:
Read uncommitted -- 不防止任何隔离性问题,具有脏读/不可重复度/虚读(幻读)问题
Read committed -- 可以防止脏读问题,但是不能防止不可重复度/虚读(幻读)问题
Repeatable read -- 可以防止脏读/不可重复读问题,但是不能防止虚读(幻读)问题
Serializable -- 数据库被设计为单线程数据库,可以防止上述所有问题
从安全性上考虑: Serializable>Repeatable read>read committed>read uncommitted
从效率上考虑: read uncommitted>read committed>Repeatable read>Serializable
真正使用数据的时候,根据自己使用数据库的需求,综合分析对安全性和对效率的要求,选择一个隔离级别使数据库运行在这个隔离级别上.
mysql 默认下就是Repeatable read隔离级别
oracle 默认下就是read committed个隔离级别
查询当前数据库的隔离级别:select @@tx_isolation;
设置隔离级别:set [global/session] transaction isolation level xxxx;其中如果不写默认是session指的是修改当前客户端和数据库交互时的隔离级别,而如果使用golbal,则修改的是数据库的默认隔离级别
脏读:一个事务读取到另一个事务未提交的数据
a 1000
b 1000
----------
a:
start transaction;
update account set money=money-100 where name=a;
update account set money=money+100 where name=b;
----------
b:
start transaction;
select * from account;
a : 900
b : 1100
----------
a:
rollback;
----------
b:
start transaction;
select* from account;
a: 1000
b: 1000
不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同 --- 行级别的问题
a: 1000 1000 1000
b: 银行职员
---------
b:start transaction;
select 活期存款 from account where name='a'; ---- 活期存款:1000
select 定期存款 from account where name='a'; ---- 定期存款:1000
select 固定资产 from account where name='a'; ---- 固定资产:1000
-------
a:
start transaction;
update accounset set 活期=活期-1000 where name='a';
commit;
-------
select 活期+定期+固定 from account where name='a'; --- 总资产:2000
commit;
----------
虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致 --- 表级别的问题
a: 1000
b: 1000
d: 银行业务人员
-----------
d:
start transaction;
select sum(money) from account; --- 2000 元
select count(name) from account; --- 2 个
------
c:
start transaction;
insert into account values(c,4000);
commit;
------
select sum(money)/count(name) from account; --- 平均:2000元/个
commit;
------------
更新丢失问题:
两个线程基于同一个查询结果进行修改,后修改的人会将先修改人的修改覆盖掉.
悲观锁:悲观锁悲观的认为每一次操作都会造成更新丢失问题,在每次查询时就加上排他锁
乐观锁:乐观锁会乐观的认为每次查询都不会造成更新丢失.利用一个版本字段进行控制
查询非常多,修改非常少,使用乐观锁
修改非常多,查询非常少,使用悲观锁
=================================================================================
二、数据库连接池
手写连接池:
改造conn的close方法
继承
装饰
!动态代理
开源数据源:
DBCP:
方式1:
BasicDataSource source = new BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUrl("jdbc:mysql:///day11");
source.setUsername("root");
source.setPassword("root");
方式2:
Properties prop = new Properties();
prop.load(new FileReader("dbcp.properties"));
BasicDataSourceFactory factory = new BasicDataSourceFactory();
DataSource source = factory.createDataSource(prop);
配置文件中:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day11
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
C3P0数据源:
方式1:
ComboPooledDataSource source = new ComboPooledDataSource();
source.setDriverClass("com.mysql.jdbc.Driver");
source.setJdbcUrl("jdbc:mysql:///day11");
source.setUser("root");
source.setPassword("root");
方式2:
ComboPooledDataSource source = new ComboPooledDataSource();
在类加载目录下名称为c3p0-config.xml的配置文件中配置:
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day11</property>
<property name="user">root</property>
<property name="password">root</property>
</default-config>
</c3p0-config>
tomcat内置的数据源(DBCP):
~1.如何为tomcat配置数据源
~tomcat/conf/context.xml文件中配置<Context>配置在这个位置的信息将会被所有的web应用所共享
~tomcat/conf/[engin]/[Host]/context.xml文件中可以配置<Context>标签,这里配置的信息将会被这台虚拟主机中的所有web应用所共享
~tomcat/conf/server.xml文件中的<Host>标签中配置<Context>标签,这是web应用的第一种配置方式,在这个标签中配置的信息将只对当前web应用起作用
~tomcat/conf/[engin]/[Host]/自己创建一个.xml文件,在这个文件中使用<Context>标签配置一个web应用,这是web应用第二种配置方式,在这个<Context>标签中配置的信息将只会对当前web应用起作用
~web应用还有第三种配置方式:将web应用直接放置到虚拟主机管理的目录.此时可以在web应用的META-INF文件夹下创建一个context.xml文件,在其中可以写<Context>标签进行配置,这种配置信息将只会对当前web应用起作用
<Resource name="mySource"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql:///day11"
maxActive="8"
maxIdle="4"/>
~2.如果在程序中获取这个数据源
想要访问jndi就必须在Servlet中才能执行下列代码:
Context initCtx = new InitialContext();
Context jndi = (Context) initCtx.lookup("java:comp/env");
DataSource source = jndi.lookUp("mySource");
---------------------------笔记---------------------------
一、事务
1.事务的概念:事务是指逻辑上的一组操作,这组操作要么同时完成要么同时不完成。参考转账操作。
2.如果你自己不去控制事务,数据库默认一条sql语句就处在自己单独的事务当中。
3.也可以使用命令去开启一个事务:
start transaction;--开启事务,这条语句之后的sql语句将处在一个事务当中,这些sql语句并不会立即执行
Commit--提交事务,一旦提交事务,事务中的所有sql语句才会执行。
Rollback -- 回滚事务,将之前所有的sql取消。
conn.setAutoCommit(false);
conn.commit();
conn.rollback();
conn.setSavePoint();
conn.rollback(sp);
4.事务的四大特性ACID
~原子性:事务的一组操作是原子的不可再分割的,这组操作要么同时完成要么同时不完成。
~一致性: 事务在执行前后数据的完整性保持不变。数据库在某个状态下符合所有的完整性约束的状态叫做数据库具有完整性。在解散一个部门时应该同时处理员工表中的员工保证这个事务结束后,仍然保证所有的员工能找到对应的部门,满足外键约束。
~隔离性:当多个事务同时操作一个数据库时,可能存在并发问题,此时应保证各个事务要进行隔离,事务之间不能互相干扰。
~持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,不能再回滚。
5.事务的隔离性导致的问题(所有的问题都是在某些情况下才会导致问题)
~脏读:一个事务读取到了另一个事务未提交的数据。
1 | a | 1000
2 | b | 1000
b--->a
start transaction;
update account set money=money-100 where name='b';
update account set money=money+100 where name='a';
rollback;
select * from account where name = 'a';1000 1000
~不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同.
start transaction:
活期存款:1000
定期存款:1000
固定资产: 2000
--------------
开启事务
取走获取存款1000
提交事务
--------------
总资产:3000
~幻读(虚读):一个事务读取到了另一个事务插入的数据(已提交)
a 2000
b 2000
c 2000
start transaction;
select sum(money) from account;6000
--------------
开启事务
创建一个账户并存入1000块钱
提交了事务
--------------
select count(*)from account;4
avgMoney = allMoney/count;6000/4=1500
6.数据库的隔离级别
~Read uncommitted:如果将数据库设定为此隔离级别,数据库将会有脏读、不可重复度、幻读的问题。
~Read committed:如果将数据库设定为此隔离级别,数据库可以防止脏读,但有不可重复度、幻读的问题。
~Repeatable read: 如果将数据库设定为此隔离级别,数据库可以防止脏读、不可重复度,但是不能防止幻读。
~Serializable:将数据库串行化,可以避免脏读、不可重复读、幻读。
安全性来说:Serializable>Repeatable read>Read committed>Read uncommitted
效率来说:Serializable<Repeatable read<Read committed<Read uncommitted
通常来说,一般的应用都会选择Repeatable read或Read committed作为数据库隔离级别来使用。
mysql默认的数据库隔离级别为:REPEATABLE-READ
如何查询当前数据库的隔离级别?select @@tx_isolation;
如何设置当前数据库的隔离级别?set [global/session] transaction isolation level ...;
~此种方式设置的隔离级别只对当前连接起作用。
set transaction isolation level read uncommitted;
set session transaction isolation level read uncommitted;
~此种方式设置的隔离级别是设置数据库默认的隔离级别
set global transaction isolation level read uncommitted;
7.做实验,演示脏读、不可重复度、幻读
~演示脏读
~演示不可重复度
~演示幻读:幻读有可能发生有可能不发生,但是一旦发生就可能造成危害。
~演示Serializable:基于锁机制运行
8.锁机制:
共享锁:共享锁和共享锁可以共存。
排他锁:排他锁和所有锁都不能共存。
在非串行化下,所有的查询都不加锁,所有的修改操作都会加排他锁。
在串行化下,所有的查询都加共享锁,所有的修改都加排他锁。
死锁
9.更新丢失
如果多个线程操作,基于同一个查询结构对表中的记录进行修改,那么后修改的记录将会覆盖前面修改的记录,前面的修改就丢失掉了,这就叫做更新丢失。
Serializable可以防止更新丢失问题的发生。其他的三个隔离级别都有可能发生更新丢失问题。
Serializable虽然可以防止更新丢失,但是效率太低,通常数据库不会用这个隔离级别,所以我们需要其他的机制来防止更新丢失:
乐观锁和悲观锁不是数据库中真正存在的锁,只是人们在解决更新丢失时的不同的解决方案,体现的是人们看待事务的态度。
悲观锁:
隔离级别不设置为Serializable,防止效率过低。
在查询时手动加上排他锁。
如果数据库中的数据查询比较多而更新比较少的话,悲观锁将会导致效率低下。
乐观锁:
在表中增加一个version字段,在更新数据库记录是将version加一,从而在修改数据时通过检查版本号是否改变判断出当前更新基于的查询是否已经是过时的版本。
如果数据库中数据的修改比较多,更新失败的次数会比较多,程序需要多次重复执行更新操作。
二、数据库连接池
1.连接池概念:
2.自己写一个连接池:
使自己的连接池在conn调用close方法是可以将连接直接返回池中:
修改一个类中某个方法的功能:
继承
装饰设计模式模式
动态代理
3.开源数据库连接池:
(1)DBCP
BasicDataSource dataSource = new BasicDataSource();
String path = this.getClass().getClassLoader().getResource("dbcp.properties").getPath();
Properties prop = new Properties();
prop.load(new FileInputStream(path));
DataSource dataSource = BasicDataSourceFactory.createDataSource(prop);
配置文件属性:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc
username=root
password=
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
(2)C3P0
ComboPooledDataSource dataSource = new ComboPooledDataSource();
ComboPooledDataSource dataSource = new ComboPooledDataSource("mySoruce");
<?xml version="1.0"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property >
<property name="jdbcUrl">jdbc:mysql:///Day12</property >
<property name="user">root</property>
<property name="password">root</property>
</default-config>
<!-- This app is massive! -->
<named-config name="mySoruce">
<property name="driverClass">com.mysql.jdbc.Driver</property >
<property name="jdbcUrl">jdbc:mysql:///Day12</property >
<property name="user">root</property>
<property name="password">root</property>
</named-config>
</c3p0-config>
driverClass
jdbcUrl
user
password
acquireIncrement:当连接池中已经没有连接时,连接池自动获取连接时一次获取的连接个数。
initialPoolSize:连接池初始化时,获取连接的个数。
maxPoolSize:连接池可以保有的最大的连接的数量。
maxIdleTime:当连接空闲多久时释放连接。如果该时间值设置问为0,表示从不释放连接。
minPoolSize:连接池应该保有的最小的连接的数量。
4.tomcat内置的数据源:tomcat内置了DBCP数据源
<1>在tomcat的安装目录下的lib目录下导入数据库驱动包
<2>在Context中配置数据源,有五个位置可以配置,参考tomcat文档
~在conf/context.xml爸爸Context中配置,这个配置将被tomcat的所有web应用共享
In the $CATALINA_BASE/conf/context.xml file: the Context element information will be loaded by all webapps.
~在conf/Catalina/localhost/context.xml,这个配置将被当前虚拟主机所共享
In the $CATALINA_BASE/conf/[enginename]/[hostname]/context.xml.default file: the Context element information will be loaded by all webapps of that host.
~在conf/Catalina/localhost/XXXXXX.xml,这是配置web应用的对外访问路径,这个配置只对当前web应用起作用
In individual files (with a ".xml" extension) in the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory. The name of the file (less the .xml extension) will be used as the context path. Multi-level context paths may be defined using #, e.g. foo#bar.xml for a context path of /foo/bar. The default web application may be defined by using a file called ROOT.xml.
~在web应用个的META-INF目录下创建context.xml这个配置只对当前web应用起作用
Only if a context file does not exist for the application in the $CATALINA_BASE/conf/[enginename]/[hostname]/, in an individual file at /META-INF/context.xml inside the application files. If the web application is packaged as a WAR then /META-INF/context.xml will be copied to $CATALINA_BASE/conf/[enginename]/[hostname]/ and renamed to match the application's context path. Once this file exists, it will not be replaced if a new WAR with a newer /META-INF/context.xml is placed in the host's appBase.
~在conf/servler.xml的Host标签下配置Context标签
Inside a Host element in the main conf/server.xml.
<3>在Cotext中配置:
<Resource name="mySource" ---在数据源创建好以后绑定到jndi容器中时使用的名字
auth="Container"
type="javax.sql.DataSource" ---当前对象的类型,默认就是数据源
username="root" --- 数据库用户名
password="root" --- 数据库密码
driverClassName="com.mysql.jdbc.Driver" ---数据库驱动名
url="jdbc:mysql:///day12" --- 数据库连接信息
maxActive="8" --- 最大连接数
maxIdle="4"/> --- 最大空闲连接数
<4>在程序中获取数据源:
Context context = new InitialContext();
Context envCtx = (Context)context.lookup("java:comp/env");
DataSource datasource = (DataSource) envCtx.lookup("mySource");
====================================
必须掌握的内容:
事务的概念
事务的四大特性
事务的4个隔离级别是什么以及如何配置
在不同的隔离级别下都分别有什么问题
更新丢失
dbcp怎么用
c3p0怎么用
tomcat数据源怎么用(JNDI知道是什么,在这里会用即可,不是重点)