一个简单实用的数据库操作框架

Java与数据库操作与框架 通过ORM框架,可以使用对象来表示数据库中的数据,从而避免了直接使用SQL语句进行数据库操作时可能出现的错误。它提供了一种标准的方法来使用SQL语句与数据库进行交互。当使用executeQuery()方法执行查询语句时,Statement对象返回一个ResultSet对象,用于存储查询结果。它提供了一种简单的方法来执行各种数据库操作,包括与数据库建立连接、创建和执行SQL语句、处理异常、关闭连接等。使用JdbcTemplate对象执行SQL语句,使用Spring JDBC框架的API来实现与数据库的交互。 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> 前言
这个小小的数据库操作封装框架是参考IBM开发网上的两篇文章并在其基础上扩充了一些功能而得到的。所以首先要感谢两篇文章的作者。
学习JDBC以来一直想实现一个简单的封装来方便编程但是由于水平有限一直没有较好的办法,看了IBM开发网上的两篇文章以后感觉作者的设计思想很好一定能扩充成一个实用的JDBC封装。所以我在文章提供的源码基础上加了一些功能这些功能包括支持多种数据类型,处理了空值,利用反射方便的在Row对象和值对象之间进行转换,还有加了一个我自认为通用的DAO类来方便用户的操作。
我把源码提供出来有两个目的一个是希望能帮助比我还初学的初学者熟悉JDBC,另外就是请各位高手不吝赐教,改进程序中的错误如果能将你们的对JDBC的封装方法提供出来那就更好了(不要说你们只用EJB或者Hibernate,JDO什么的)。
IBM开发网的那两篇文章分别是《一个简单的 JDBC 包装器》《对一个简单的 JDBC 包装器的扩展及应用》,我的邮箱是xsimple2003@yahoo.com.cn有事请与我联系。
设计思想
 把DBMS抽象成类Database,这个类负责管理数据库连接以及提供表对象。
 把数据库中的一张或多张表抽象成类Table,这个类中提供对表的添加,修改,删除的JDBC封装。
 将数据库表中的一条记录抽象成类Row,这个类用HashMap保存关系数据库中表格中一行数据的字段名和值并提供一些相关操作。另外这个类还提供了两个静态方法用于在Row对象和ValueObject之间进行方便的转换。
 把对个Row的集合抽象成RowSet,这个类中用一个vector把多个Row对象保存起来并提供一些相关操作。
代码分析
由于已经给出源码所以我只对代码中关键的和需要注意的地方加以说明,大家可以执行源码一边演示一边体会。
 Database类源码如下:
package com.gdrj.util.database;
import java.sql.*;
import javax.sql.*;
import com.gdrj.util.servicelocator.*;
public class Database {
/**
* 这个数据库连接成员只有在与数据库直接建立连接的情况下是有效的
*/

private Connection conn = null;
/**
* 当这个参数有效时,表明程序是直接与数据库建立的连接而不是从连接池里取得连接
*/

private String url, user, password;
/**
* 当这个参数有效时,表明程序是从连接池里取得连接。
*/

private String datasource;
/**
* 用数据库地址,用户名,密码初始化数据库对象,这个构造器用于程序是直接
* 与数据库建立连接的情况。
* @param url
* @param user
* @param password
*/

public Database(String url, String user, String password) {
this.url = url;
this.user = user;
this.password = password;
}

/**
* 用JNDI数据源名初始化数据库对象,这个构造器用于从连接池取数据库连接的情况。
* @param datasource
*/

public Database(String datasource) {
this.datasource = datasource;
}

/**
* 得到数据库连接,对于是否从连接池里取连接做了自动处理即根据用户调用了哪个构造器
* 来判断是否直接与数据库建立连接还是从连接池里取连接。
* 对于用户来说不用考虑程序是从那里取得连接,他只管正确的初始化数据库对象。
* @return
* @throws SQLException
*/

public Connection getConnection() throws Exception {
if (datasource == null) { //直接与数据库建立连接

if (conn == null) {
conn = DriverManager.getConnection(url, user, password);
}
}
else { //从应用服务器的连接池里取得连接

ServiceLocator sl = ServiceLocator.getInstance();
DataSource ds = sl.getDataSource(datasource);
return ds.getConnection();//每调用一次都返回一个连接池中的数据库连接

}
return conn;
}

/**
* 释放连接,如果是直接与数据库连接的情况则什么也不做
* 如果是从连接池中取得的连接那么释放传来的连接
* @param conn
*/

public void disConnect(Connection connection) {
if (datasource != null) { //只处理从连接池取连接的情况

try {
if (connection != null) {
connection.close();
}
}
catch (Exception ex) {}
}
}

/**
* 得到与参数名对应的表对象,注意这里不作任何数据库操作
* @param name
* @return
*/

public Table getTable(String name) {
return new Table(this, name);
}
}

这个类是对DBMS的抽象,所以使用时应用程序中只要有一个Database对象就够了,如果你是以与数据库之间建立连接的方式使用那么你用Database(String url, String user, String password)构造器进行初始化。如果是从应用服务器的连接池中取得连接的方式使用那么用Database(String datasource)构造器初始化,这样以后你使用这个对象进行getConnection和disConnection时就不用去考虑始终保持一个连接(C/S方式),还是将连接返回连接池了因为在disConnection中已经做了处理。集体使用方法将Table类。在getConnection中的从连接池中取连接的代码你只要参考以下《J2EE核心模式》中的服务定位器模式就知道是怎么回事了,你在用Database(String url, String user, String password)初始化时其中的代码不起作用。
 Table类源码如下:
package com.gdrj.util.database;
import java.sql.*;
import java.util.*;
import com.gdrj.util.*;
public class Table {
/**
* 通过这个数据库对象得到数据库连接
*/

private Database database;
/**
* 数据库中一个或多个(只限查询)表的名
*/

private String name;
/**
* 初始化表对象,此时不作任何数据库相关操作
* 一般通过database的getTable调用
* @param database
* @param name
*/

public Table(Database database, String name) {
this.database = database;
this.name = name;
}
/**
* 查询某一行
* @return
*/

public Row getRow(String fields, String criteria, Object[] args) throws
DBAccessException {
RowSet rows = executeQuery(fields, criteria, args);
if (rows == null) {
return null;
}
return rows.get(0);
}
/**
* 得到一个多行记录
* @param criteria 查询条件
* @param args 查询条件的参数列表
* @return
*/

public RowSet getRows(String fields, String criteria, Object[] args) throws
DBAccessException {
return executeQuery(fields, criteria, args);
}
/**
* 执行SQL查询
* @param fields 要查询的字段,如果传入null则表示查询表中所有字段
* @param criteria用户输入的查询Where条件
* @param args 用到的参数数组
* @return 返回符合结果行集
*/

private RowSet executeQuery(String fields, String criteria, Object[] args) throws
DBAccessException {
Connection conn = null;
RowSet rows = new RowSet();
String sql = null;
if (fields == null) {
fields = "*";
}
try {
conn = database.getConnection(); //取得数据库连接,在方法内部对不同的连接情况进行了处理

sql = "select " fields " from " name
( (criteria == null) ? "" :
(" where " criteria));
PreparedStatement pstmt = conn.prepareStatement(sql);
if (args != null) { //如果有查询参数则设置参数

for (int i = 0; i < args.length; i ) {
pstmt.setObject(i 1, args[i]);
}
}
ResultSet rs = pstmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int cols = rsmd.getColumnCount();
/**@todo 判断是否为零*/

if (cols == 0) {
return null;
}
while (rs.next()) {
Row row = new Row();
for (int i = 1; i <= cols; i ) {
String name = rsmd.getColumnName(i);
Object value = rs.getObject(i); //作通用类型处理,这样row中的类型都是Object型的。

/**
* 这里要做空值处理,因为在进行RowToValueObject转换时如果是空值则不能得到值的类型
* 所以如果是空值那么把value设置成类型信息
*/

if (value == null) {
value = Class.forName(rsmd.getColumnClassName(i));
}
// System.out.println(value.getClass());//用于得到数据库中的类型对应Java中的什么类型

row.put(name, value);
}
rows.add(row);
}
rs.close();
pstmt.close();
}
catch (Exception ex) {
throw new DBAccessException(InforGeter.getErrorInfor(this, "executeQuery",
ex, "执行SQL(" sql ")查询时出错!"));
}
finally {
database.disConnect(conn); //调用数据库对象的释放连接方法(此方法内对取得连接方式的不同情况做了处理)

}
return rows;
}
/**
* 增加一行
* @param row
*/

public int putRow(Row row) throws DBAccessException {
return putRow(row, null, null);
}
/**
* 修改一行(没有条件就是增加)
* @param row
* @param conditions
*/

public int putRow(Row row, String conditions, Object[] args) throws
DBAccessException {
String ss = "";
int affectableRow = 0; //执行SQL后影响的行数

if (conditions == null) {
ss = "INSERT INTO " name "(";
for (int i = 0; i < row.length(); i) {
String k = row.getKey(i);
ss = k;
if (i != row.length() - 1) {
ss = ", ";
}
}
ss = ") VALUES (";
for (int j = 0; j < row.length(); j) {
ss = (row.get(j) == null) ? "null" : "?"; //如果row中有空值则设置为null,否则设置为查询参数

if (j != row.length() - 1) {
ss = ", ";
}
}
ss = ")";
}
else {
ss = "UPDATE " name " SET ";
for (int i = 0; i < row.length(); i) {
String k = row.getKey(i);
ss = k "=" ( (row.get(i) == null) ? "null" : "?"); //设置查询参数

if (i != row.length() - 1) {
ss = ", ";
}
}
ss = " WHERE ";
ss = conditions;
}
Connection conn = null;
try {
conn = database.getConnection();
PreparedStatement st = conn.prepareStatement(ss);
int j = 0; //查询参数计数器

for (int i = 0; i < row.length(); i ) {
if (row.get(i) != null) { //如果不是空则解析查询参数

st.setObject( j, row.get(i)); //解析查询参数

}
}
if (args != null) {
for (int i = 0; i < args.length; i ) {
st.setObject( j, args[i]);//预定的规则,null不能放到查询参数中要以name=null的静态形式存放

}
}
affectableRow = st.executeUpdate();
st.close();
}
catch (Exception ex) {
ex.printStackTrace();
throw new DBAccessException(InforGeter.getErrorInfor(this, "putRow", ex,
"更新表" name "中的数据时出错!"));
}
finally {
database.disConnect(conn);
}
return affectableRow;
}

/**
* 删除一行
* @param row
*/

public int delRow(Row row) throws DBAccessException {
String ss = "";
int affectableRow = 0;
ss = "delete from " name " where ";

for (int i = 0; i < row.length(); i) {
String k = row.getKey(i);
ss = k ((row.get(i) == null)?" is null":"=?"); //设置查询参数有空值处理

if (i != row.length() - 1) {
ss = " and ";
}
}
Connection conn = null;
try {
conn = database.getConnection();
PreparedStatement st = conn.prepareStatement(ss);
int j = 0;//查询参数计数器

for (int i = 0; i < row.length(); i ) {
if (row.get(i) != null) {
st.setObject( j, row.get(i)); //解析查询参数

}
}
affectableRow = st.executeUpdate();
st.close();
}
catch (Exception ex) {
throw new DBAccessException(InforGeter.getErrorInfor(this, "delRow", ex,
"删除表" name "中的数据时出错!"));
}
finally {
database.disConnect(conn);
}
return affectableRow;
}
/**
* 有条件的删除即删除多行
* @param condition
* @param args
*/

public int delRow(String condition, Object[] args) throws DBAccessException {
String ss = "";
int affectableRow = 0;
ss = "delete from " name " where ";
ss = condition;
Connection conn = null;
try {
conn = database.getConnection();
PreparedStatement st = conn.prepareStatement(ss);
if (args != null) {
for (int i = 0; i < args.length; i ) {
st.setObject(i 1, args[i]);
}
}
affectableRow = st.executeUpdate();
st.close();
}
catch (Exception ex) {
throw new DBAccessException(InforGeter.getErrorInfor(this, "delRow", ex,
"删除表" name "中的数据时出错!"));
}
finally {
database.disConnect(conn);
}
return affectableRow;
}
}

使用时可以用Database对象的getTable方法传入数据库表的名称来得到一个Table对象。得到这个对象后就可以对这个数据库表进行操作了,这个类提供了六个方法根据传过来的参数对数据库表进行添加修改删除操作。代码中没有特别难懂的地方,需要注意的是我在原有代码的基础上对空值进行的处理,在查询时如果表中的数据是空值的话那么我把字段对应的Java类型放到Row对象里,因为在进行Row对象到值对象的转换时用到了java反射API必须知道Row中的字段值的类型才能去调用值对象的setXXXX方法(见Row对象的toValueObject方法)。
 行对象的源码如下:
package com.gdrj.util.database;
import java.util.*;
import java.math.BigDecimal;
import java.lang.reflect.*;
public class Row {
/**
* 排序,由于Hashtable不提供通过索引取得值的方法,并且其中的键值对也不是按照put上去时的顺序排列的。
* 注意:Vector中加入的对象是有序的,即按加入的顺序排列并且能够根据索引访问,可以看成是可变大小的数组
* List可以取代Vector
*/

private Vector ordering = new Vector();
/**
* 存放键值对(表中字段名称与字段值)
*/

private HashMap map = new HashMap();
public Row() {
}
/**
* 向HashMap中追加键值对,即字段名称与字段值
* @param name
* @param value
*/

public void put(String name, Object value) {
if (!map.containsKey(name)) {
ordering.addElement(name); //将键保存起来

}
map.put(name, value);
}
/**
* 得到行对象中字段的个数
* @return
*/

public int length() {
return map.size();
}
/**
* 根据字段名称取得字段值
* @param name
* @return
*/

public Object get(String name) {
return map.get(name);
}
/**
* 根据字段在HashMap中的编号取得字段值
* @param which
* @return
*/

public Object get(int which) {
String key = (String) ordering.elementAt(which);
return map.get(key);
}
/**
* 根据字段序号取得字段名称
* @param which
* @return
*/

public String getKey(int which) {
String key = (String) ordering.elementAt(which);
return key;
}
/**
* 打印,用于调试
*/

public void dump() {
for (Iterator e = map.keySet().iterator(); e.hasNext(); ) {
String name = (String) e.next();
Object value = map.get(name);
System.out.print(name "=" value ", ");
}
System.out.println("");
}
/**
* 将行对象转换成值对象
* @param row
* @param type值对象类型
* @return
* @throws java.lang.Exception 这里的异常一般在DAO中处理,因为DAO调用
* 这个方法进行Row和ValueObject的转换
*/

public static Object toValueObject(Row row, Class type) throws Exception {
Object vo = type.newInstance(); //创建一个值对象

Field[] fields = type.getDeclaredFields(); //得到值对象中所有字段

for (int i = 0; i < fields.length; i ) {
String name = fields[i].getName(); //得到JavaBean的字段名

String nameInRow = toInRowName(name);//在此进行值对象名称到行对象名称的转换

Object value = row.get(nameInRow); //得到从数据库中取出的与字段名对应的值

String methodName = "set" Character.toUpperCase(name.charAt(0))
name.substring(1); //得到setXXXX方法名

Class argClass = null;
if (value instanceof Class) {
argClass = (Class)value;
value = null;
}else{
argClass = value.getClass();
}
Method method = type.getMethod(methodName, new Class[] {argClass}); //得到set方法

method.invoke(vo, new Object[] {value});//调用setXXXX方法

}
return vo;
}
/**
* 根据传过来的值对象和类型把值对象转换到行对象中
* @param vo
* @return
* @throws java.lang.Exception 这里的异常一般在DAO中处理,因为DAO调用
* 这个方法进行Row和ValueObject的转换
*/

public static Row fromValueObject(Object vo) throws Exception {
Row row = new Row();
Class type = vo.getClass(); //得到Class用于进行反射处理

Field[] fields = type.getDeclaredFields();
for (int i = 0; i < fields.length; i ) {
String name = fields[i].getName();
String methodName = "get" Character.toUpperCase(name.charAt(0))
name.substring(1);
Method method = type.getMethod(methodName, new Class[] {});
Object value = method.invoke(vo, new Object[] {});
String nameInRow = toInRowName(name);//在此进行值对象中的名称向行对象中的名称转换

row.put(nameInRow, value);
}
return row;
}
/**
* 将值对象中属性名转换成对应的行对象中的字段名(因为行对象中的字段名
* 在更新数据库时必须与数据库表中字段名完全匹配)
* 一般规则为 fsiId ---> fsi_id(现在假设的情况是如果出现有两个单词
* 以上的值对象属性名则数据库表中的字段名一定是有下划线的)
* @param voName
* @return
*/

public static String toInRowName(String voName) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < voName.length(); i ) { //遍历voName如果有大写字母则将大写字母转换为_加小写

char cur = voName.charAt(i);
if (Character.isUpperCase(cur)) {
sb.append("_");
sb.append(Character.toLowerCase(cur));
}
else {
sb.append(cur);
}
}
return sb.toString();
}
}

Row对象中用了一个HashMap对象存放着对应数据库表中的字段名和对应值,由于Map对象的无序性,所以用了一个vector(当然也可以用List代替)来存放字段名(按用户添加的顺序)这样就可以提供get(int i)方法来顺序取得Map中的值了。要注意的是三个静态辅助方法toValueObject,fromVauleObject,toInRowName。toValueObject方法用于将一个行对象转换为值对象方法中利用了Java的多态和反射机制(请大家参考反射API)。FromValueObject是上一个方法的逆操作,toInRowName方法是实现值对象中的属性名向数据库表中字段名的转换,因为一般在数据库建表时是用的这种形式stu_id,而Java中JavaBean的属性是这样的stuId。
 RowSet的代码如下:
package com.gdrj.util.database;
import java.util.*;
public class RowSet {
private Vector vector = new Vector();

public RowSet() {
}

public void add(Row row) {
vector.addElement(row);
}

public int length() {
return vector.size();
}

public Row get(int which) {
if (length() < 1) {
return null;
}
else {
return (Row) vector.elementAt(which);
}
}

public void dump() {
for (Enumeration e = vector.elements(); e.hasMoreElements(); ) {
( (Row) e.nextElement()).dump();
}
}
}

这个类就是把Row对象放到Vector以便操作。就不多说了。
 为了方便使用我写了一个GeneralDAO类(我对DAO模式还在理解中请各位高手批评指教)代码如下:
package com.gdrj.util.database;
import java.util.*;
public class GeneralDAO {
/**
* 这个DAO对应的表对象
*/

private Table table;
/**
* 默认构造函数
*/

public GeneralDAO() {
}

/**
* 用数据库对象和表名初始化DAO
* @param db
* @param tableName
*/

public GeneralDAO(Database db, String tableName) {
getTable(db, tableName);
}
private void getTable(Database db, String name) {
table = db.getTable(name);
}
/**
* 根据条件将查找到的数据以值对象集合的形式返回
* @param fields 要查找的字段(*或null表示所有字段)
* @param criteria查询条件
* @param args与查询条件对应的参数数组
* @param voType值对象的类型
* @return
* @throws java.lang.Exception
*/

public Collection findDatas(String fields, String criteria, Object[] args,
Class voType) throws Exception {
RowSet rows = table.getRows(fields, criteria, args);
Collection col = new ArrayList();
for (int i = 0; i < rows.length(); i ) {
Object vo = Row.toValueObject(rows.get(i), voType); //返回一个值对象,注意是voType类型的对象

col.add(vo);
}
return col;
}

/**
* 向表中插入一条数据
* @param vo 与表对象对应的值对象
* @return
* @throws java.lang.Exception
*/

public int insertData(Object vo) throws Exception {
return table.putRow(Row.fromValueObject(vo));
}

/**
* 更新一条数据
* @param vo 与表对象对应的值对象
* @param criteria更新条件
* @param args与更新条件对应的参数数组
* @return
* @throws java.lang.Exception
*/

public int updateData(Object vo, String criteria, Object[] args) throws
Exception {
return table.putRow(Row.fromValueObject(vo), criteria, args);
}

/**
* 删除一条数据(条件比较严格各个字段的值必须与值对象中属性的值匹配)
* @param vo
* @return
* @throws java.lang.Exception
*/

public int deleteData(Object vo) throws Exception {
return table.delRow(Row.fromValueObject(vo));
}
/**
* 删除多条数据
* @param condition 删除条件
* @param args与条件对应的参数数组
* @return
* @throws java.lang.Exception
*/

public int deleteDatas(String condition, Object[] args) throws Exception {
return table.delRow(condition, args);
}
}

这个DAO类是对Table类的一个方便的封装。用户如果向操作数据库只要创建一个Database对象,一个DAO对象,一个值对象(对应表结构),然后就可以进行方便的数据库操作了,下面给出一个实例来演示这个小小框架的用法。
演示程序
首先建立一个teacher表,语法如下
create table teacher (
id int not null,
name varchar(20) not null,
birthday smalldatetime null,
address varchar(100) null,
income money null,
constraint id PRIMARY KEY NONCLUSTERED ( id )
)
然后建立一个与teacher表对应的值对象类。
public class TeacherVO implements Serializable {
private Integer id;
private String name;
private String address;
private BigDecimal income;
private java.sql.Timestamp birthday;
public TeacherVO() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public java.sql.Timestamp getBirthday() {
return birthday;
}
public void setBirthday(java.sql.Timestamp birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public java.math.BigDecimal getIncome() {
return income;
}
public void setIncome(java.math.BigDecimal income) {
this.income = income;
}
public String toString(){
return " 编号:" id " 姓名:" name " 生日:" birthday
" 地址:" address " 收入:" income;
}
}

最后主程序的源码如下:
package org.together.jdbcwrap.test;
import java.util.*;
import com.gdrj.util.database.*;

public class GeneralDAOExample {
public static void main(String[] args)throws Exception {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Database db = new Database("jdbc:odbc:emmis","sa","815023");
GeneralDAO dao = new GeneralDAO(db,"teacher");
/**
* 利用GeneralDAO进行查询
*/

Collection col = dao.findDatas("*","birthday is null",null,TeacherVO.class);
for (Iterator iter = col.iterator(); iter.hasNext(); ) {
Object item = iter.next();
System.out.println("item = " item);
}
/**
* 利用GeneralDAO进行添加
*/

TeacherVO vo = new TeacherVO();
vo.setAddress("沈阳");
vo.setBirthday(new java.sql.Timestamp(0));
vo.setId(new Integer(11));
vo.setIncome(new java.math.BigDecimal(1000));
vo.setName("陶小川");
// dao.insertData(vo); //添加一条记录

// dao.updateData(vo,"id=10",null); //更新一条记录

// dao.deleteData(vo); //删除一条记录

// dao.deleteDatas("id>5",null); //添加符合条件记录

}
}

Java数据库快速开发框架(数据库快速开发框架)。- fast-sql / FastSQL 轻量级数据库访问框架FastSQL 目录 1 简介 FastSQL一个基于spring-jdbc的简单ORM框架,它支持sql构建、sql执行、命名参数绑定、查询结果自动映射和通用DAO。结合了Hibernate/JPA快速开发和Mybatis高效执行的优点。 FastSQL可以完全满足你控制欲,可以用Java代码清晰又方便地写出sql语句并执行。 FastSQL完全可用于生产环境,相比Mybatis,使用简单,开发效率高。 2 入门 2.1 安装 如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中: <dependency> <groupId>top.fastsql</groupId> <artifactId>fastsql</artifactId>    <version>1.3.0</version> </depe 立即下载

相关推荐

SpringBoot整合oceanbase,实现oracle无缝切换到oceanbase

随着去“IOE”化的潮流,近些年来,许多与国家相关的项目不约而同到地往”国产化“方向靠拢,不可避免地,一些项目可能需要进行数据库迁移。

4624

博客系统后端设计(二) - 封装数据库操作

创建一个 db.sql 文件、封装数据库的连接操作、创建实体类、封装数据库的增删改查操作

超烦豆先森 875

ADB命令解锁Android手机屏幕的3种实用方法(附详细步骤)

本文详细介绍了在Android手机屏幕失灵或密码遗忘时,利用ADB命令解锁屏幕的三种实用方法。包括通过ADB模拟输入事件、移除锁屏认证文件(需Root权限)以及结合恢复模式抢救数据。文章提供了详细的操作步骤与风险提示,强调提前开启USB调试的重要性,是Android用户应对紧急锁屏情况的有效技术指南。

weixin_29229055的博客 924

23---WPF数据库ORM框架

4.底层当然还是Sql语句---中间必然有一个实体对象到Sql语句的生成过程--通用的,通过程序来生成SQL语句---Sql语句不是那么简洁--Sql语句相对比较僵化---读取类中的元素,生成Sql语句---必然会大量的反射---反射损耗性能。2.ORM: object-relational-mapping对象关系映射--对象--类--可以通过对类的操作完成对于数据库的操作---对类的操作---面向对象的编程思想;一、仓库--存放货物---数据库--存放数据--关系型数据/非关系型数据库。

qq_58563355的博客 2475

基于DPLL算法解决3-SAT问题(C++实现)

近日看到一个3-SAT问题(Boolean SATisfiability Problem, 布尔逻辑可满足性问题),试着写了个算法求解。

qq_63241496的博客 2218

基于PyTorch的BP神经网络PID控制器动态调参实战

本文详细介绍了基于PyTorch的BP神经网络PID控制器动态调参实战,结合BP神经网络的自适应能力和PID控制算法的经典优势,实现工业控制中的高效参数调整。通过PyTorch实现BP-PID融合架构,包括网络设计、损失函数优化及动态调参技巧,显著提升控制性能,适用于温度控制、电机控制等场景。

weixin_29094775的博客 523

Java框架之ORM

本文看下Java操作数据库相关的内容。

wang0907的博客 3469

PLL锁相环性能上不去?可能是电荷泵的电流失配在捣鬼(附Jae-Shin Lee经典方案解析)

本文深入分析了PLL锁相环性能瓶颈的根源——电荷泵电流失配问题,详细解析了Current Mismatch和Current Deviation的区别及其对系统的影响。重点介绍了Jae-Shin Lee的多级电流镜技术,该方案通过运放构建虚拟短路和四级电流镜结构,显著降低了电流失配,使参考杂散改善15dB以上。文章还提供了从仿真到流片的完整优化流程,帮助工程师系统解决电荷泵性能问题。

weixin_30684743的博客 371

Java与数据库:JDBC和ORM框架的使用和效率优化

随着互联网的快速发展和大数据时代的到来,数据库在软件开发中起到了至关重要的作用。Java作为一门强大而广泛应用的编程语言,提供了多种与数据库交互的方式。其中,JDBC和ORM框架是最常用的两种方式。本文将深入探讨JDBC和ORM框架的使用方法,并分享一些提高效率的优化技巧。JDBC(Java Database Connectivity)是Java平台的一种标准数据库访问技术。它提供了一组用于执行SQL语句和访问数据库的API。下面我们通过一个简单的示例来演示JDBC的使用。import java.sql.*

baidu_38876334的博客 1421

10款AI工具赋能虚拟展厅设计:架构师效率提升90%的秘密武器

2020年全球疫情成为数字转型的催化剂,虚拟展厅从"可选项"迅速转变为"必需品"。根据Gartner最新报告,到2025年,超过70%的企业将采用虚拟展厅作为客户体验和产品展示的核心渠道。这一转变不仅是应急措施,更是商业模式的永久性革新。虚拟展厅突破了物理空间的限制——一个精心设计的虚拟展厅可以同时接待来自全球各地的访客,无需考虑场地容量;展品可以以数字形式永久保存,避免了物流和损耗问题;数据分析功能可以精确追踪每位访客的行为轨迹,提供前所未有的洞察。数据透视。

AI 领航者的博客 1573

动网格-网格重构之铺层(三)

运动区域可以是边界区域 (Boundary Zone),也可以是单元区域 ( Cell Zone)。指定了体网格再生方法后,FLUENT自动地根据运动区域(dynamic zones)的运动来调整内部节点以再生体网格。必须保留至少一层网格。(4)如果边面的法向和运动方向偏角较大,生成的网格扭斜度会比较大铺层算法不适用于边界形状变化较大的情况。(1)体网格再生方法的选择(Smoothing,Layering,Remeshing);(2)适用网格种类:四边形、六面体、三棱柱(网格的分布要服从一定的规则)。

weixin_44386973的博客 2096

一个简单实用的数据库操作框架(JAVA)

前言这个小小的数据库操作封装框架是参考IBM开发网上的两篇文章并在其基础上扩充了一些功能而得到的。所以首先要感谢两篇文章的作者。学习JDBC以来一直想实现一个简单的封装来方便编程但是由于水平有限一直没有较好的办法,看了IBM开发网上的两篇文章以后感觉作者的设计思想很好一定能扩充成一个实用的JDBC封装。所以我在文章提供的源码基础上加了一些功能这些功能包括支持多种数据类型,处理了

5977

AD-Copilot 论文解读:把“大模型看图”升级为“对照检验”的工业异常检测助手

本文提出AD-Copilot,一个面向工业异常检测的视觉语言助手,通过视觉上下文比较解决现有方法的不足。针对工业场景中多模态大模型表现不佳的问题,作者指出核心原因在于缺乏工业数据和比较能力不足。为此,论文提出三个关键贡献:构建Chat-AD数据集,设计Comparison Encoder显式建模图像差异,以及采用多阶段训练策略。实验表明,该方法在MMAD基准上达到82.29%准确率,定位任务提升3.35倍,并展现出良好的泛化能力。消融实验验证了比较模块的有效性,表明其成功源于高质量比较数据与显式比较模块的协

blanokvaffy的博客 334

java 操作mysql框架_一个简单实用的数据库操作框架(JAVA)

前言这个小小的数据库操作封装框架是参考IBM开发网上的两篇文章并在其基础上扩充了一些功能而得到的。所以首先要感谢两篇文章的作者。学习JDBC以来一直想实现一个简单的封装来方便编程但是由于水平有限一直没有较好的办法,看了IBM开发网上的两篇文章以后感觉作者的设计思想很好一定能扩充成一个实用的JDBC封装。所以我在文章提供的源码基础上加了一些功能这些功能包括支持多种数据类型,处理了空值,利用反射方便的...

weixin_33138569的博客 1066

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: JVM结构基础(一)
下一篇: tomcat怎么设置跟iis那种类似的访问密码
java169
博客等级 码龄19年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值