??xml version="1.0" encoding="utf-8" standalone="yes"?> statement,resultset属于弱refrenceQ即如果statementxQresultset׃被自动释??
refrence的做法不保险Q所以JDBC3.0开始明规定了如果connection被关Q所有statement都应该关,不过q取决于使用的数
据库驱动?br />应该DBMS 执行操作后,昑ּ的关闭statement Q因为在connection关闭前,JDBC statement仍旧处于打开状态,当返回resultset后,关闭statement是必要的Q尤其在遇到异常的时候?br />如果不用connection pool可以直接关闭connectionQ不考虑statement的关闭,使用q接池的时候,务必关闭statementQ否则你的连接马上被用光Q用statement pooling除外?/p>
http://www.w3china.org/blog/more.asp?name=hongrui&id=10283
2,Software caused connection abort: socket write error 最l找C原因:sql写错了,写成了where name='?'
有h说原?
spring对oracle的clob和StoredProcedure 的处?/a>
l过几天的夜战,l于知道使用spring对oracle的存储过E操作,E序L的真正原因,一旦执行存储过E没有Q何返回|因ؓ “Statement.getUpdateCount() returns 1 instead of -1”,是oracle的驱动的bugQ?0.1.0.2的驱动就不行Q听?0.1.0.3没有问题,但是10.1.0.3的jdbc驱动不能下蝲。大家可以用weblogic8.1SP3带的10.1.0.2或weblogic9beta?0.1.0.2Q可以解册个问题。不知道开?oracle jdbc的程序员是什末hQ没毕业的大学生Q还是拖Ơ了工资的程序员Q开发水q不如开源数据库的jdbc驱动的h呢,再次oracle驱动最好是自己命名Q把文g名加上版本信息,要不会死人的?br /> http://72.5.124.102/thread.jspa?messageID=1424984 http://group.gimoo.net/review/44109 http://azi.javaeye.com/blog/182146 http://hi.baidu.com/happyidea/blog/item/c84b313de75add0abba16779.html
3,Random Connection Closed Exceptions These can occur when one request gets a db connection from the connection
pool and closes it twice. 见http://tomcat.apache.org/tomcat-4.1-doc/jndi-datasource-examples-howto.html String sql="select s_id as sid,s_name as sname,s_sex as ssex,s_brith as sbrith from stu"; List list=this.getJdbcTemplate().query(sql,new BeanPropertyRowMapper(Stu.class)); return list; } 关于execute和updateҎ之间的区别,updateҎq回的是受媄响的记录数目?一个计敎ͼq且如果传入参数的话Q用的是java.sql.PreparedStatement,而executeҎL使用 java.sql.Statement,不接受参敎ͼ而且他不q回受媄响记录的计数Q更适合于创建和丢弃表的语句Q而updateҎ更适合于插入,更新 和删除操作,q也是我们在使用旉要注意的?/span> Connection conn=DataSourceUtils.getConnection(getJdbcTempldate().getDataSource()); conn=getJdbcTemplate().getNativeJdbcExtractor().getNativeConnection(conn); OracleConnection oconn=(OracleConnection)conn; 通过DataSourceUtils获取当前U程l定的数据连接,Z使用U程上下文相关的事务Q这样写是正的写法Q如果直接从DataSource获取q接Q得到的是和当前U程上下文无关的新的数据库连接实例?/span> http://www.javaeye.com/topic/49932?page=2 http://www.javaeye.com/problems/15846 http://www.javaeye.com/topic/87034 http://www.javaeye.com/topic/508799 http://ttitfly.javaeye.com/blog/151560 jdbcTemplate的方式里如果带上int[] argTypes昄指定每个占位W所对应的字D|据类型,可以保证cd安全Q当参数gؓnullӞ提供了更好的支持?/p> ----------------------- 上面q句话如何理解? 后在http://javazoo.bokee.com/viewdiary.15850865.html扑ֈ原因?/p> 今天在调试程序的时?在后C务逻辑cM利用JdbcTemplateq行数据同步操作?发现?br />执行jdbcTemplate.update(?的SQL语句,new Object[]{tmp.getName( ),tmp.getNo( ),tmp.getSpeciality( ),tmp.getMounterofficer( ),tmp.getDesigner( ),tmp.getProductivity( ),tmp.getState( )) 如果字段名和属性名是严格对应的Q那么就可以不用自己写RowMapper了,使用BeanPropertyRowMapper: getJdbcTemplate().query(sql, new BeanPropertyRowMapper(User.class)); cȝ属性字D名U要数据库中的字D名UCh者数据库字段名ؓs_idcȝ名称为SId, //l定参数Ӟ日期cd的写?未经q验?br /> public void updStu(Stu stu) { ConnectionCallback的用法,使用完要手动关闭q接吗? spring的AbstractRoutingDataSourceQ可以多态切换数据库? 事务抽象层http://blog.csdn.net/congqian1120/archive/2008/01/16/2046311.aspx
ArrayHandler Q将ResultSet中第一行的数据转化成对象数l?br />ArrayListHandler : ResultSet中所有的数据转化成ListQList中存攄是Object[]
BeanHandler Q将ResultSet中第一行的数据转化成类对象
BeanListHandler Q将ResultSet中所有的数据转化成ListQList中存攄是类对象
MapHandler Q将ResultSet中第一行的数据存成Map映射
MapListHandler Q将ResultSet中所有的数据存成List。List中存攄是Map
ColumnListHandler Q将ResultSet中某一列的数据存成ListQList中存攄是Object对象
KeyedHandler Q将ResultSet中所有数据存成MapQMap中key为某一列的|value为MapQ存放key对应的行的数?br />ScalarHandler Q将ResultSet中一条记录的其中某一列的数据存成Object
查询的基本用?
String jdbcDriver = "com.mysql.jdbc.Driver";
String user = "root";
String password = "root";
DbUtils.loadDriver(jdbcDriver);
Connection conn = null;
try {
conn = DriverManager.getConnection(url, user, password);
QueryRunner qr = new QueryRunner();
List results = (List)qr.query(conn, "select * from T_USER", new BeanListHandler(User.class) );
} catch (SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
} params)
throws SQLException {
Connection conn = this.prepareConnection();
try {
return this.query(conn, sql, rsh, params);
} finally {
close(conn);
}
}
扩展ApacheCommos的DbUtils以支持字D名下划U映?/a>
?DBUtils 包中 BeanProcessor 的优?/a>
修改DbUtils支持表名下划U映?/a>
dbutils
Commons DbUtils 源码阅读?/a>
让你的DBUtils支持enum
OSChina底层数据库操作的c?QueryHelper)源码
OSChina底层数据库操作的c?QueryHelper)源码2
ZJDBC+Oracle+Apache Dbutil的泛型DAO
日常数据库操作的烦恼及解?-DbUtils、MyBatis和Hibernate
Zdbutils支持annotation的简易orm
]]>
Availability(可用?,
好的响应性能
Partition tolerance(分区定w? 可靠?/span>
CAP原理指的是,q三个要素最多只能同时实C点,不可能三者兼?br />http://www.javaeye.com/articles/2367
BASE模型反ACID模型Q完全不同ACID模型Q牺牲高一致性,获得可用性或可靠性:
Basically
Available基本可用。支持分区失?e.g. sharding片划分数据?
Soft state软状?
状态可以有一D|间不同步Q异步?br />Eventually consistent最l一_最l数据是一致的可以了Q而不是时旉一致?br />http://lovewhzlq.javaeye.com/blog/619965
Sharding:
Sharding(分片)Q与分区(Partition)不一P分区不能跨数据库
http://www.dbanotes.net/database/database_sharding.html
]]>
]]>
1)
TYPE_FORWARD_ONLY是默认?
仅支持结果集forward
Q不支持滚动,也不?/span>
SENSITIVE?br />2)
ResultSet.TYPE_SCROLL_INSENSITIVE,
支持l果?span lang="EN-US">backforward Q?span lang="EN-US">last
Q?span lang="EN-US">first
{操作,对其?span lang="EN-US">sessionҎ据库中数据做出的更改是不敏感?/span>
原因:JDBCҎ据库q行数据查询executeQueryӞ数据库会创徏查询l果的cache和cursorQ如下面sql:
select name,id from foo
用jdbc执行上面的sql语句Ӟ数据库会把foo表所有记录的name和id字段~存到cache中,之后cache和真正的数据库数据文件没有Q何联pMQfoo表发生的改变在查询完成后不会自动同步到cache上去Q因此TYPE_SCROLL_INSENSITIVE寚w择数据做出的更Ҏ不敏
感,不可见?br />3)ResultSet.TYPE_SCROLL_SENSITIVE
支持l果?span lang="EN-US">backforward
Q?span lang="EN-US">last
Q?span lang="EN-US">first
{操作,对其?span lang="EN-US">sessionҎ据库中数据做出的更改是敏感的Q即其他session
修改了数据库中的数据Q会反映到本l果集中
上面的select name,id from foo语句用TYPE_SCROLL_SENSITIVE的Statement来执行,会{化成以下的sql语句Q?br />
select rowid from foo
数据库这时候是把foo表所有记录的rowid~存到cache中,用户代码在fetch记录Ӟ再l做以下查询Q?br />
select name,id from foo where rowid=?
因此q时候发生的查询是实时从真正的数据库数据文g中取Q因此对期间发生的数据更Ҏ可见的,敏感的。但是这U可见性仅限于update操作Q?
insert和delete同样是不可见的。因为如果查询发生在insert之前Qinsert生成的rowidq不会反应在cache中的rowidl果集上。在一个记录的rowid已经~存到cache中,q时候被删除了,但一般数据库的删除是标记删除Q也是说rowid对应那行记录q没有真正从?
据库文g中抹去,一般是可以再次取到记录的?br />
l论Q是?span>SENSITIVE?/span>fetchsize没有什么关pR?/span>是否SENSITIVE是告诉数据库如何作查询的~存?/span>fetchsize是客Ljdbc的设|?br />
另外oracle?/span>fetchsize默认?0Q?/span>
stmt.setFetchSize(0)时stmt.getFetchSize()=10
stmt.setFetchSize(1)时stmt.getFetchSize()=1
另外如果查询的sql复杂Ӟ我发现就设?/span>ResultSet.TYPE_SCROLL_SENSITIVE也不起作用,?/span>
select t.* from test t left join testp p on t.pid=p.id where p.title like '%?'Q在q行中修改title的|发现仍然可以取到。是否可以理解ؓSENSITIVE只对查询的主表v作用?/span>
摘自Q?br />http://www.javaeye.com/topic/128636
http://www.javaeye.com/topic/560109
http://www.javaeye.com/topic/418604
]]>
oracle数据库连接与q接池之间冲H导?
oracle database把空闲一D|间的q接关闭了,而应用服务器q接池却认ؓ该边接还是可用的Q再ơ访问时q是使用该连接,D出现q接异常?br />Ҏ,当然是改数据库配|了.
]]>
http://www.javaeye.com/problems/6124
select count(*) num from lottery_term where term_issuenum in (?) and
term_lotteryid = ?
ҎgetJdbcTemplate().queryForInt(sql,new Object[]{new
String[]{"2008326","2008325","2008324"},103});
List
list=new ArrayList();
list.add("****");
getJdbcTemplate().queryForInt(sql,new
Object[]{list,103});
?br />select count(*) from info_document where category_id in
(:category_id_list);
Map<String,Object> parm = new
HashMap<String,Object>();
parm.put("category_id_list", idList);
public List getAllStu() {
q种操作?如果后面参数中有gؓnull?后台会报异常,l想下也?如果是null,那就要执行jdbc的setNull(Spring底层q是用JDBC做的)Ҏ?但是setNullҎ要知道具体的数据库字D늚cd.如setNull(1,Types.VARCHAR).而在上面的方法没有体?
l于体会到updateҎ中第三个参数new int[]的作用了.!
springq是很伟大的.
如果你没有遵守这个规范则可以在select语句后面l数据库字段名取别名
String sql = "update stu set s_name=?,s_sex=?,s_brith=? where s_id=?";
Object[] obj = new Object[] { stu.getSname(), stu.getSsex(),new java.sql.Date(stu.getSbrith().getTime()), stu.getSid() };
getJdbcTemplate().update(sql, obj, new int[] { Types.VARCHAR, Types.VARCHAR,Types.DATE, Types.INTEGER });
}
http://www.oracle.com/technology/global/cn/pub/articles/marx_spring.html
]]>
?/span> Spring 的支持,使用 JDBC 变得如此单,我们不会再因为它的复杂性而将其的优先U打个折扣。可是,如果我们选择使用某个特定?/span> ORM 工具Q那么我们就很难用基?/span> JDBC ?/span> DAO 实现q行替换了——目前我们就是这栗当我们同时在一个类中包含了 JDBC ?/span> hibernate 代码Ӟ我们无法?/span> Spring 提供的支持。因为我们的 DAO 只能扩展 HibernateDaoSupport ?/span> JdbcDaoSupport 二者之一。幸q的是,q里有一个优雅的解决ҎQ它允许我们?/span> Hibernate ?/span> JDBC 代码装在同一个类之内Q而不会因此失?/span> Spring 的支持。这个方案的关键在于?/span> JDBC 代码装在内部类中,之后主?/span> DAO 的调用委托给q个内部cd完成。代码清?/span> 11-6 提供了一个示例:
代码清单 11-16. 在一个单独的 DAO 中合?/span> Hibernate ?/span> JDBC
package com.apress.prospring.ch11.canonicalization;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
public class MyDao extends HibernateDaoSupport {
private MyJdbcDao innerDao;
public MyDao() {
innerDao = new MyJdbcDao();
}
public void update(MyDomainObject obj) {
// use Hibernate to persist the data
}
public MyDomainObject getById(int someId) {
return innerDao.getBy(someId);
}
private static class MyJdbcDao extends JdbcDaoSupport {
public MyDomainObject getBy(int someId) {
// do some real processing
return null;
}
}
}
管q只是一个简单的实现Q我们也可以从中得到启发。所有的 JDBC 相关代码都被转移C个内部类中,而此内部cL展了 JdbcDaoSupport , 所有的 Hibernate 相关功能都留在外部,外部cM然是 HibernateDaoSupport . 的子cR通过q个c,我们可以使用 Hibernate 完成域对象的持久化,但是我们可以查询功能交l嵌入的 JDBC DAO d成?/span>
在我们的应用中有效利用标准化 Q可以通过避免大量无谓对象的创建,从而极大提升内存用效率。如果我们必L新标准化对象相关的数据,同时我们?/span> DAO 中用了 ORM 框架Q那么我们就可以?/span> ORM 无关的Ş式引入一?/span> JDBC 代码来加入标准化 支持?/span>
来源:Pro Spring中文?http://book.csdn.net/bookfiles/48/100481407.shtml
http://hi.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/blog/item/7768d41e8c06ceffe0fe0ba6.html
public interface ConnectionCallback
Generic callback interface for code that operates on a JDBC Connection. Allows to execute any number of operations on a single Connection, using any type and number of Statements.
This is particularly useful for delegating to existing data access code
that expects a Connection to work on and throws SQLException. For newly
written code, it is strongly recommended to use JdbcTemplate's more specific
operations, for example a query
or updat
variant.
ObjectdoInConnection(Connection con)
throws SQLException,
DataAccessException
JdbcTemplate.execute
with an active JDBC
Connection. Does not need to care about activating or closing the
Connection, or handling transactions.
If called without a thread-bound JDBC transaction (initiated by DataSourceTransactionManager), the code will simply get executed on the JDBC connection with its transactional semantics. If JdbcTemplate is configured to use a JTA-aware DataSource, the JDBC Connection and thus the callback code will be transactional if a JTA transaction is active.
Allows for returning a result object created within the callback, i.e.
a domain object or a collection of domain objects. Note that there's special
support for single step actions: see JdbcTemplate.queryForObject
etc. A thrown RuntimeException is treated as application exception:
it gets propagated to the caller of the template.
con
- active JDBC Connection
null
if none
SQLException
- if thrown by a JDBC method, to be auto-converted
to a DataAccessException by a SQLExceptionTranslator
DataAccessException
- in case of custom exceptionsJdbcTemplate.queryForObject(String, Class)
,
JdbcTemplate.queryForRowSet(String)
创徏试用表
CREATETABLE T_TEST(
I_ID NVARCHAR(20),
I_NAME NVARCHAR(20)
)
一Q无q回值的存储q程
1、徏立存储过E?br />
CREATE OR REPLACE PROCEDURE TESTA(PARA1 IN VARCHAR2,PARA2 IN VARCHAR2) AS
BEGIN
INSERT INTO T_TEST (I_ID,I_NAME) VALUES (PARA1, PARA2);
END TESTA;
2、相应的JAVAE序
import java.sql.*;
import java.io.OutputStream;
import java.io.Writer;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import oracle.jdbc.driver.*;
public class TestProcedureOne {
public TestProcedureOne() {
}
public static void main(String[] args ){
String driver = "oracle.jdbc.driver.OracleDriver";
String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
CallableStatement cstmt = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(strUrl, "dbname", "password");
CallableStatement proc = null;
proc = conn.prepareCall("{ call dbname.TESTA(?,?) }");
proc.setString(1, "100");
proc.setString(2, "TestOne");
proc.execute();
}
catch (SQLException ex2) {
ex2.printStackTrace();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
finally{
try {
if(rs != null){
rs.close();
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
}
}
catch (SQLException ex1) {
}
}
}
}
二:有返回值的存储q程Q非列表Q?/span>
1、存储过Eؓ
CREATE OR REPLACE PROCEDURE TESTB(PARA1 IN VARCHAR2,PARA2 OUT VARCHAR2) AS
BEGIN
SELECT INTO PARA2 FROM TESTTB WHERE I_ID= PARA1;
END TESTB;
2、JAVA代码
public class TestProcedureTWO {
public TestProcedureTWO() {
}
public static void main(String[] args ){
String driver = "oracle.jdbc.driver.OracleDriver";
String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(strUrl, "dbname", "password");
CallableStatement proc = null;
proc = conn.prepareCall("{ call HYQ.TESTB(?,?) }");
proc.setString(1, "100");
proc.registerOutParameter(2, Types.VARCHAR);
proc.execute();
String testPrint = proc.getString(2);
System.out.println("=testPrint=is="+testPrint);
}
catch (SQLException ex2) {
ex2.printStackTrace();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
finally{
try {
if(rs != null){
rs.close();
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
}
}
catch (SQLException ex1) {
}
}
}
}
}
注意Q这里的proc.getString(2)中的数?qL的,而是和存储过E中的out列对应的Q如果out是在W一个位|,那就?
proc.getString(1)Q如果是W三个位|,是proc.getString(3)Q当然也可以同时有多个返回|那就是再多加几个out
参数了?br />
三:q回列表
׃oracle存储q程没有q回|它的所有返回值都是通过out参数来替代的Q列表同样也不例外,但由于是集合Q所以不能用一般的参数Q必要用pagkage?所以要分两部分?br />
1、在SQL*PLUS中徏一个程序包
CREATE OR REPLACE PACKAGE TESTPACKAGE AS
TYPE Test_CURSOR IS REF CURSOR;
procedure TESTC(cur_ref out Test_CURSOR);
end TESTPACKAGE;
建立存储q程Q存储过EؓQ?br />
create or replace package body TESTPACKAGE as
procedure TESTC(cur_ref out Test_CURSOR) is
begin
OPEN cur_ref FOR SELECT * FROM T_TEST;
end TESTC;
END TESTPACKAGE;
可以看到Q它是把游标Q可以理解ؓ一个指针)Q作Z个out 参数来返回值的?br />
JAVAE序如下Q?/p>
import java.sql.*;
import java.io.OutputStream;
import java.io.Writer;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import oracle.jdbc.driver.*;
public class TestProcedureOne {
public TestProcedureOne() {
}
public static void main(String[] args ){
String driver = "oracle.jdbc.driver.OracleDriver";
String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
CallableStatement cstmt = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(strUrl,"databasename" "password");
CallableStatement proc = null;
proc = conn.prepareCall("{ call cqsb.TESTA(?,?) }");
proc.setString(1, "100");
proc.setString(2, "TestOne");
proc.execute();
}
catch (SQLException ex2) {
ex2.printStackTrace();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
finally{
try {
if(rs != null){
rs.close();
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
}
}
catch (SQLException ex1) {
}
}
}
}
特别注意Q?br /> 1、在执行前一定要先把oracle的驱动包攑ֈclass路径里?br /> 2、Toad在我建立存储q程中搞了很多莫名的错误Q多数是没有创徏成功而不报错Q?br /> 或者是创徏有误而不提示Q应当引起重视。所以最好还是在SQL*PLUS玩这些?br /> 3、在SQL*PLUS中的换行是无效的Q要换行的时候一定要I格l尾Q特别是你直接复制代码的时候!
?/span> Web 目中,ȝq发昑־其严重。例如,用户 A 和用?/span> B 同时修改数据库中的某张表?/span> R 行,加入 R 行有两个字段分别?/span> C1 Q?/span> C2 ?/span>
假如按照如下q程修改Q?/span>
1 用户 A 数?/span> R Q?/span> C1,C2 Q读取到 A 的浏览器中?/span>
2 用户 B 数?/span> R Q?/span> C1,C2 Q读取到 B 的浏览器中?/span>
3 用户 A 在浏览器上将数据修改?/span> R Q?/span> C1?/span> Q?/span> C2 Q,同时更新到数据库?/span>
4 用户 B 在浏览器上将数据修改?/span> R Q?/span> C1 Q?/span> C2?/span> Q,同时更新到数据库?/span>
上述q程存在两个问题Q第一Q第 4 ?/span> B 在修Ҏ据的时候数据库中的数据?/span> B 的浏览器中数据已l不一致了Q第二,如果E序按照哪个字段变化在数据库中更新哪个字D늚方式处理的话Q那么经q上q四步修改,数据库中 R 行的内容是( C1?C2?/span> Q,q和 A 或?/span> B 的想法都不同Q?/span> A 认ؓ是( C1?/span> Q?/span> C2 Q, B 认ؓ是( C1 Q?/span> C2?/span> Q)?/span>
上述q程?/span> A Ҏ据库的修改过E或?/span> B Ҏ据库的修改过E,都是无法Ҏ数据库的最新内容做修改Q所以成为离Uѝ?/span> A ?/span> B 同时对记?/span> R q行p叫离Uѝ?/span>
以上的环境叫ȝq发?/span>
那么如何解决ȝq发q程中遇到的问题呢?我们引入锁机制?/span>
锁机?/span>
锁机Ӟ是在需要修改的数据上加互斥锁,通过互斥锁避免数据被同时修改。锁机制更具其应用环境又分ؓ乐观?/strong>?strong style="">悲观?/strong>
乐观?/span>
乐观锁,指认为冲H很发生,所以只是在数据修改的时候比较修改的基础数据和数据库中的数据是否相同Q相同则修改Q否则提C用户重新装入数据库中已l变化的数据?/span>
实现Ҏ 1 Q在q行 update 的时候?/span> where 条gQ在 Where 标间中比较所有上一步中查询得到的数据。如果数据库中的数据没有变化Q则 update 可以更新到内容,否则 update 语句不能更新到内容,可以Ҏ update 的返回值确定更新是否成功?/span>
实现Ҏ 2 Q在每一个表中追加一个特D字D,cd?/span> timestamp Q每ơ更新的时候比较这个字D늚值是否一_如果一_则更斎ͼ同时这个字D|Cؓ当前旉Q否则,说明数据已经变更。这也可以?/span> update 加上 where 实现?/span>
悲观?/span>
悲观锁指Q需要修改的数据Q在d的时候就Ҏ据加锁,其他用户在准备修改,d数据的阶D判断数据是否上锁,以此来决定是否进行修改前的读操作?/span>
实现ҎQ?/span>
通常在数据库中徏立一?/span> lock 表,该表的字D包括,表明Q唯一索引Q时_用户信息{?/span>
在用戯取数据准备修改的时候,首先判断 lock 表中是否存在自己要d的数据?/span>
如果不存在,则在 lock 表中d一条记录,记录寚w张表的哪行数据进行修改;如果存在Q在判断旉字段是否时?/span>
如果时Q则更新 lock 表中本条记录的时间字Dc?strong style="">Q防止死锁的必要手段Q?/strong>
如果存在Q也不超Ӟ说明本条记录正在被其他用户修改,则返回ƈ发信息?/span>
出处:http://blog.csdn.net/struts2/archive/2007/08/14/1742686.aspx