BaseDaoUtils(基于dbUtil实现)

1 篇文章 0 订阅
1 篇文章 0 订阅

        因为最近学习了dbutils,感觉多数的表都用共同的操作(增删改查),刚好也闲,就顺手做了个BaseDao,dao层的类只需要继承BaseDaoImpl类就可以用使用基本的增删改查。

用前须知(请一定要仔细观看):

内容:

        根据所学的c3p0,基于dbUtils,进行了进一步的封装

        当然,相对于框架来说,这简直拉跨太多了,我当时还没有学习到框架,就只是单纯的练习与学习。

作用一,(Dao的实现类(继承jarBaseDaoImpl的类))

可以直接用 此类[.insert][.update][.delete][.selectById][.selectAll]

        这5个方法(继承与jar包的BaseDaoImpl类有这些方法),因此不需要编写这些方法,直接使用即可

用法:

1、导入相关jar包和c3p0-config.xml到项目的src目录下

(依赖:mysql-connector-java-8.0.16.jar,mchange-commons-java-0.2.19.jar,commons-dbutils-1.7.jar,c3p0-0.9.5.5.jar,baseDaoUtil1.2.jar)

2、建数据库和表

3、修改,配置c3p0-config.xml文件

4、编写表对应的bean类(字段名要相同)

(导入baseDaoUtil.jar包)

5、编写DAO层的接口,并继承cn.hnzj.hhao.dao.BaseDao接口

6、编写DAO的事项类,并继承cn.hnzj.hhao.dao.impl.BaseDaoImpl类

(如果自己编写的DAO事项类类名与数据库表名不同,可通过设置BaseDaoImpl的tableName属性设置,默认为DAO实现类的类名《可通过构造方法中调用super(tableName)》)

注:

(1)DAO继承时的泛型为表对应的bean类

(2)bean类要求:字段名和数量与数据库表对应,id属性名需为:(id名可以是id 或 <表名>id 或 <表名的首字母>id 或 <表名的首字母>-id 不区分大小写)

(3)如果bean类名与数据库的表名不同,需要调用父类的有参构造方法(参数为String类型<表名>),设置表名

(4)bean字段的fianl字段不会被识别。

(5)我使用的是mysql数据库,如果数据库不同,要更改数据库驱动jar包和xml对应的驱动名和值),jdk为17.0.1

作用二,(C3P0Utils)
1、提供数据源对象
2、提供数据库连接对象
3、提供QueryRunner对象
4、查询当前数据库下的所有表名
5、查询某个表的所有字段

用法:直接用C3P0Utils.<方法>


jar包依赖:

c3p0-0.9.5.5.jar

commons-dbutils-1.7.jar

mchange-commons-java-0.2.19.jar

mysql-connector-java-8.0.16.jar

baseDaoUtil1.2.jar


c3p0-config.xml c3p0的配置文件(必须放在src根目录下,名称也不能改)

<?xml version="1.0" encoding="UTF-8"?>
<!-- 文件名 -->
<c3p0-config>
	<default-config>
		<!-- 数据库驱动名 -->
		<property name="driverClass" >com.mysql.cj.jdbc.Driver</property>
		<!-- 数据库的url -->
		<property name="jdbcUrl" >jdbc:mysql://localhost:3306/mysql?serverTimeZone=UTC</property>
		<!-- 数据库名称 -->
		<property name="user" >root</property>
		<!-- 数据库密码 -->
		<property name="password" >123456</property>
		<!-- chechoutTimeout:等三秒检查 -->
		<property name="checkoutTimeout" >3000</property>
		<!-- 初始化时的连接数量 -->
		<property name="initialPoolSize" >10</property>
		<!-- 连接池内最大的连接数量 -->
		<property name="maxPoolSize" >100</property>
		<!-- 连接池内最小的连接数量 -->
		<property name="minPoolSize" >10</property>
		<!-- 连接池中缓存PrepareStatement的总数 -->
		<property name="maxStatements" >200</property>
	</default-config>
	<!-- test数据库 -->
	<named-config name="test">
		<property name="driverClass" >com.mysql.cj.jdbc.Driver</property>
		<property name="jdbcUrl" >jdbc:mysql://localhost:3306/test?serverTimezone=UTC</property>
		<property name="user" >root</property>
		<property name="password" >123456</property>
		<property name="checkoutTimeout" >3000</property>
		<property name="initialPoolSize" >10</property>
		<property name="maxPoolSize" >10</property>
	</named-config>
</c3p0-config>

下方为源代码:


BaseDao:

package cn.hnzj.hhao.dao;

import java.util.List;

/**
 * Title: BaseDao Description: 实现数据库的基本操作
 * 
 * @author HhaoAn
 * @date 2021年12月10日
 */
public interface BaseDao<T> {

	/**
	 * Title: insert Description: 通过对象插入数据
	 */
	int insert(T t) throws Exception;

	/**
	 * Title: update Description: 通过对象更改对应id的数据
	 */
	int update(T t) throws Exception;

	/**
	 * Title: delete Description: 通过对象的id属性删除数据
	 */
	int delete(T t) throws Exception;

	/**
	 * Title: selectById Description: 通过对象的id的属性查询数据
	 */
	T selectById(T t) throws Exception;

	/**
	 * Title: selectAll Description: 查询所有的数据
	 */
	List<T> selectAll() throws Exception;

}

        注:会抛出自定义异常,下方有自定义异常类的源代码(我认为,抛出中文的异常说明还是好看懂,所以顺手做了异常)。 

BaseDaoImpl:

package cn.hnzj.hhao.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import cn.hnzj.hhao.dao.BaseDao;
import cn.hnzj.hhao.exception.FieldDaoException;
import cn.hnzj.hhao.exception.TableNameDaoException;
import cn.hnzj.hhao.exception.DaoException;
import cn.hnzj.hhao.util.C3P0Utils;

/**
 * Title: BaseDao Description: 进行数据库的基本操作
 * 用法:子类继承数据连接层,继承此类,泛型用要操作的表对应的bean类。并保证Bean对象和数据库的字段名一致
 * (id,<表名>id,<表名的首字母>id,<表名的首字母>-id 不区分大小写)
 * 
 * 比如:user表对应的bean类为User则泛型写<User> 《User [id,username,userpassword]》,《User
 * [userid,username,userpassword]》,《User [userId,username,userpassword]》,《User
 * [uId,username,userpassword]》,《User [u-Id,username,userpassword]》
 * 
 * 如果类名与表名不对应: 泛型依旧用对应的Bean类,但是要重新设置表名字段:在子类调用父类的有参构造方法中传入表名
 * 
 * 如:public UserDaoImpl() throws DaoException { super("user"); }
 *
 * @author HhaoAn
 * @date 2021年12月9日
 */
public class BaseDaoImpl<T> extends Thread implements BaseDao<T> {
	// 操作语句常量
	private static final String INSERT = "insert";
	private static final String UPDATE = "update";
	private static final String DELETE = "delete";
	private static final String SELECTBYID = "selectbyid";
	private static final String SELECTALL = "selectall";
	/** runner:执行sql操作 */
	private static QueryRunner runner = null;
	/** entityClass:子类的类 */
	private Class<T> entityClass = null;
	/** tableName:子类的类名(表名) */
	private String tableName = null;
	/** idIndex:子类表的id下标 */
	private int idIndex = 0;
	private Field[] fields = null;

	public BaseDaoImpl() {// 创建子类对象时会调用父类的无参构造方法,从而实现赋值
		init();// 初始化信息
		try {
			// 检测标准
			fieldCheck();
		} catch (DaoException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Title: Description: 提供表名,修改泛型的表名
	 * 
	 * @param tableName
	 */
	public BaseDaoImpl(String tableName) {// 创建子类对象时会调用父类的无参构造方法,从而实现赋值
		init();// 初始化信息
		this.tableName = tableName.toLowerCase();
		System.out.println(this.tableName);
		try {
			// 检测标准
			fieldCheck();
		} catch (DaoException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Title: insert Description: 通过对象插入数据
	 * 
	 * @param 需要添加的对象
	 * @return 执行后,影响的行数
	 */
	@Override
	public int insert(T t) {
		int row = -1;
		try {
			row = runner.update(getSql(INSERT), setArgs(INSERT, t));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return row;
	}

	/**
	 * Title: update Description: 通过对象更改对应id的数据
	 * 
	 * @param 需要修改的对象(需要含有id值)
	 * @return 执行后,影响的行数
	 */
	@Override
	public int update(T t) {
		int row = -1;
		try {
			row = runner.update(getSql(UPDATE), setArgs(UPDATE, t));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return row;
	}

	/**
	 * Title: delete Description: 通过对象的id属性删除数据
	 * 
	 * @param 需要删除的对象(需要含有id值)
	 * @return 执行后,影响的行数
	 */
	@Override
	public int delete(T t) {
		int row = -1;
		try {
			return runner.update(getSql(DELETE), setArgs(DELETE, t));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return row;
	}

	/**
	 * Title: selectById Description: 通过对象的id的属性查询数据
	 * 
	 * @param 需要查询的对象
	 * @return 执行后,查找的一个对象
	 */
	@Override
	public T selectById(T t) {
		try {
			t = runner.query(getSql(SELECTBYID), new BeanHandler<T>(entityClass), setArgs(SELECTBYID, t));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return t;
	}

	/**
	 * Title: selectAll Description: 查询所有的数据
	 * 
	 * @param 需要查询的对象
	 * @return 执行后,对应表的所有信息
	 */
	@Override
	public List<T> selectAll() {
		List<T> result = null;
		try {
			result = runner.query(getSql(SELECTALL), new BeanListHandler<T>(entityClass));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * Title: getSql Description: 获取sql语句
	 * 
	 * @throws Exception
	 */
	private String getSql(String operation) throws Exception {
		StringBuffer sql = new StringBuffer();
		switch (operation) {
		case INSERT:// 插入语句 insert into <table> values(?,?...);
			sql.append("insert into ").append(tableName).append(" values(");
			for (int i = 0; i < fields.length; i++)
				sql.append("?,");
			sql.deleteCharAt(sql.length() - 1);
			sql.append(");");
			break;
		case UPDATE:// 修改语句 update <table> set *=?,*=?... where <id>=?;
			sql.append("update ").append(tableName).append(" set ");
			for (int i = 0; i < fields.length; i++)
				if (i != idIndex)
					sql.append(fields[i].getName()).append("=?,");
			sql.deleteCharAt(sql.length() - 1);
			sql.append(" where ").append(fields[idIndex].getName()).append("=?;");
			break;
		case DELETE:// 删除语句 delete from <table> where <id>=?;
			sql.append("delete from ").append(tableName).append(" where ").append(fields[idIndex].getName())
					.append("=?;");
			break;
		case SELECTBYID:// 通过id查询语句 select * from <table> where <id>=?;
			sql.append("select * from ").append(tableName).append(" where ").append(fields[idIndex].getName())
					.append("=?;");
			break;
		case SELECTALL:// 查询全部语句 select * from <table>
			sql.append("select * from ").append(tableName);
			break;
		default:// 操作参数传入异常,产生错误,阻止程序继续运行
			throw new Exception("getSql方法的传入参数有误");
		}
		return sql.toString();
	}

	/**
	 * Title: setArgs Description: 把参数包装为数组
	 * 
	 * @throws Exception
	 */
	private Object[] setArgs(String operation, T t) throws Exception {
		Object[] args = null;
		switch (operation) {
		case INSERT:// 插入语句 [*,*,*...]
			args = new Object[fields.length];
			for (int i = 0; i < args.length; i++) {
				fields[i].setAccessible(true);
				args[i] = fields[i].get(t);
			}
			break;
		case UPDATE:// 修改语句 [*,*,*...,<id>]
			args = new Object[fields.length];
			for (int i = 0; i < args.length; i++) {
				fields[i].setAccessible(true);
				if (i < idIndex)
					args[i] = fields[i].get(t);
				else if (i == idIndex)
					args[args.length - 1] = fields[idIndex].get(t);
				else
					args[i - 1] = fields[i].get(t);
			}
			break;
		case DELETE:// 删除语句 删除和通过id查询都只需要<id>参数,可以共用
		case SELECTBYID:// 通过id查询语句
			fields[idIndex].setAccessible(true);
			args = new Object[] { fields[idIndex].get(t) };
			break;
		default:// 操作参数传入异常,产生错误,阻止程序继续运行
			throw new Exception("setArgs方法的第一个传入参数有误");
		}
		return args;
	}

	/**
	 * Title: init Description: 初始化信息
	 */
	@SuppressWarnings("unchecked") // 不报错提示
	private void init() {
		// 获取QueryRunner对象,进行sql语句操作
		runner = C3P0Utils.getQueryRunner();
		// 获取泛型参数
		ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();// this.getClass()等价于getClass();
		// 获取泛型的类
		entityClass = (Class<T>) type.getActualTypeArguments()[0];
		// 获取子类的表名 .substring(0, getClass().getSimpleName().length() - 4)
		tableName = entityClass.getSimpleName().toLowerCase();
		// 排除常量字段
		List<Field> var = new ArrayList<Field>();
		for (Field field : entityClass.getDeclaredFields()) {// 如果不是fianl修饰字段,则添加到列表中
			if (!java.lang.reflect.Modifier.isFinal(field.getModifiers()))
				var.add(field);
		}
		fields = new Field[var.size()];
		fields = var.toArray(fields);
	}

	/**
	 * Title: fieldCheck Description: 检查格式是否匹配
	 */
	private void fieldCheck() throws DaoException {
		List<String> tableNames = C3P0Utils.getTableNames();
		// 判断表名是否存在
		if (!tableNames.contains(tableName))
			throw new TableNameDaoException(tableNames, tableName);
		List<String> columnNames = C3P0Utils.getColumnNames(tableName);
		List<String> fields = new ArrayList<String>();
		for (Field field : this.fields)
			fields.add(field.getName());
		// 判断字段名是否匹配
		if (!(fields.containsAll(columnNames) && columnNames.containsAll(fields)))
			throw new FieldDaoException(entityClass.getSimpleName(), tableName, fields, columnNames);
		// 获取id属性值的下标
		for (String field : fields) {
			if (field.equalsIgnoreCase("id") || field.equalsIgnoreCase(tableName + "id")
					|| field.equalsIgnoreCase(tableName.substring(0, 1) + "id")
					|| field.equalsIgnoreCase(tableName.substring(0, 1) + "-" + "id"))// 存在时,直接结束
				break;
			idIndex++;// 下标加以
		}
		// 下标等于字段数组的长度时,说明没有找到id属性,报错
		if (idIndex == this.fields.length)
			throw new FieldDaoException(entityClass.getSimpleName());
	}
}

异常类:(处理BaseDaoImpl抛出的异常)

DaoException:自定义报错的父类

package cn.hnzj.hhao.exception;

/**
 * Title: DaoException Description: 数据连接层的基本报错
 * 
 * @author HhaoAn
 * @date 2021年12月12日
 */
public class DaoException extends Exception {

	/** serialVersionUID: */
	private static final long serialVersionUID = 1L;

	public DaoException() {
		// TODO Auto-generated constructor stub
		super("数据库表结构和Bean类不匹配或无法连接数据库");
	}

	public DaoException(String info) {
		// TODO Auto-generated constructor stub
		super(info);
	}

}

C3P0ParamDaoException: 数据库连接的报错

package cn.hnzj.hhao.exception;

/**
 * Title: ParamDaoException Description: 数据库没有成功连接时的报错
 * 
 * @author HhaoAn
 * @date 2021年12月10日
 */
public class C3P0ParamDaoException extends DaoException {

	/** serialVersionUID: */
	private static final long serialVersionUID = 1L;

	/**
	 * Title: Description: 报错信息
	 */
	public C3P0ParamDaoException() {
		// TODO Auto-generated constructor stub
		super("无法连接数据库,请检查您的c3p0-config文件内的参数是否正确的与数据库匹配,或更改了c3p0-config文件的名称,位置等");
	}
}

FieldDaoException:字段是否匹配的报错

package cn.hnzj.hhao.exception;

import java.util.List;

/**
 * Title: FieldDaoException Description: 数据库与bean类字段问题
 * 
 * @author HhaoAn
 * @date 2021年12月12日
 */
public class FieldDaoException extends DaoException {

	/** serialVersionUID: */
	private static final long serialVersionUID = 1L;

	public FieldDaoException(String beanName) {
		// TODO Auto-generated constructor stub
		super("您的" + beanName + "类的id属性名与默认的id名(id,<表名>id,<表名的首字母>id,<表名的首字母>-id 不区分大小写)不匹配");
	}

	public FieldDaoException(String beanName, String tableName, List<String> fields, List<String> columnNames) {
		// TODO Auto-generated constructor stub
		super("您的" + beanName + "类属性名有:" + fields + "与数据库内" + tableName + "表的字段名:" + columnNames + "数量或名称不匹配");
	}

}

RunSqlDaoException:运行时传入参数的报错(基本上时不可能遇到)

package cn.hnzj.hhao.exception;

public class RunSqlDaoException extends DaoException{

	/** serialVersionUID:*/
	private static final long serialVersionUID = 1L;

	public RunSqlDaoException(Object obj) {
		// TODO Auto-generated constructor stub
		super("请检查:"+obj+"的参数是否合法(类型不匹配或id为空值)");
	}
}

TableNameDaoException:表名不匹配时的报错

package cn.hnzj.hhao.exception;

import java.util.List;

/**
 * Title: TableNameDaoException Description: 未在相应数据库下找到表名
 * 
 * @author HhaoAn
 * @date 2021年12月12日
 */
public class TableNameDaoException extends DaoException {

	/** serialVersionUID: */
	private static final long serialVersionUID = 1L;

	public TableNameDaoException() {
		// TODO Auto-generated constructor stub
		super("表名与数据库内表名不对应(如果您未设置表名需要bean类名与表名相同,或在继承类上设置tableName属性,或当前的数据库下并没有这个表)");
	}

	public TableNameDaoException(List<String> tableNames, String tableName) {
		// TODO Auto-generated constructor stub
		super("未读取到对应的表,当前数据库下存在表有:" + tableNames + "当前读取到的表名为:" + tableName + "(如果您需要设置" + tableName
				+ "的类名与数据库内的表名相同,或在继承BaseBean的类的构造方法上调用父类的有参构造方法(设置表名))");
	}
}

C3P0Utils:数据源的工具类

package cn.hnzj.hhao.util;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ColumnListHandler;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import cn.hnzj.hhao.exception.C3P0ParamDaoException;

/**
 * Title: C3P0Utils Description: 获取数据库连接 记得根据自己的数据库调整c3p0-config.xml的参数
 * 
 * @author HhaoAn
 * @date 2021年12月6日
 */
public class C3P0Utils {
	/** ds:声明一个数据源 */
	public static DataSource ds;
	static {
		ds = new ComboPooledDataSource("test");// 创建一个test数据库数据源对象
	}

	/**
	 * Title: getDataSource Description: 获取数据源
	 * 
	 * @return DataSource
	 */
	public static DataSource getDataSource() {
		return ds;
	}

	/**
	 * Title: getConnection Description: 获取一个连接
	 * 
	 * @return Connection
	 */
	public static Connection getConnection() throws SQLException {
		return ds.getConnection();
	}

	/**
	 * Title: getQueryRunner Description: 获取一个QueryRunner对象
	 * 
	 * @return QueryRunner
	 */
	public static QueryRunner getQueryRunner() {
		return new QueryRunner(ds);
	}

	/**
	 * Title: getColumnNames Description: 获取数据库下的所有表名
	 * 
	 * @return List<String>
	 * @throws C3P0ParamDaoException
	 */
	public static List<String> getTableNames() throws C3P0ParamDaoException {
		try {
			return getQueryRunner().query("show tables;", new ColumnListHandler<String>());
		} catch (SQLException e) {
			// TODO: handle exception
			e.printStackTrace();
			throw new C3P0ParamDaoException();
		}
	}

	/**
	 * Title: getColumnNames Description: 获取表中所有字段名称
	 * 
	 * @param tableName 表名
	 * @return List<String>
	 * @throws C3P0ParamDaoException
	 */
	public static List<String> getColumnNames(String tableName) throws C3P0ParamDaoException {
		try {
			return getQueryRunner().query("desc " + tableName, new ColumnListHandler<String>());
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new C3P0ParamDaoException();
		}
	}
}

以下为自己测试时用的代码:

 UserBean:用户表对应的封装对象

package cn.hnzj.hhao.bean;

import java.io.Serializable;

/**
 * Title: user Description: userbean
 * 
 * @author HhaoAn
 * @date 2021年12月6日
 */
public class UserBean implements Serializable {
	/** serialVersionUID: */
	private static final long serialVersionUID = 1L;
	private int userid;
	private String username;
	private String password;

	/**
	 * Title: Description:
	 */
	public UserBean() {
		super();
	}

	/**
	 * Title: Description:
	 * 
	 * @param userid
	 * @param username
	 * @param password
	 */
	public UserBean(int userid, String username, String password) {
		super();
		this.userid = userid;
		this.username = username;
		this.password = password;
	}

	/**
	 * @return the userid
	 */
	public int getUserid() {
		return userid;
	}

	/**
	 * @param userid the userid to set
	 */
	public void setUserid(int userid) {
		this.userid = userid;
	}

	/**
	 * @return the username
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * @param username the username to set
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @param password the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/*
	 * (non-Javadoc) Title: toString Description:
	 * 
	 * @return
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "UserBean [userid=" + userid + ", username=" + username + ", password=" + password + "]";
	}
}

UserDao:用户数据库操作的对应类

package cn.hnzj.hhao.dao;

import java.sql.SQLException;

import cn.hnzj.hhao.bean.UserBean;

/**
* Title: UserDao Description: 实现用户表的基本操作
* @author HhaoAn
* @date 2021年12月10日
*/
public interface UserDao extends BaseDao<UserBean>{

	/**
	 * Title: selectByUserName Description: 通过用户名查询用户
	 */
	UserBean selectByUserName(UserBean user) throws SQLException;

}


UserDaoImpl:用户数据库操作的对应类(因为Bean名与表名不对应,所以需要调用父类的有参构造方法设置tableName)

package cn.hnzj.hhao.dao.impl;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import cn.hnzj.hhao.dao.UserDao;
import cn.hnzj.hhao.bean.UserBean;
import cn.hnzj.hhao.util.C3P0Utils;

public class UserDaoImpl extends BaseDaoImpl<UserBean> implements UserDao {

	public UserDaoImpl() {
		// TODO Auto-generated constructor stub
		super("User");
	}
	
	/**
	 * Title: selectByUserName Description: 通过用户名查询用户
	 */
	@Override
	public UserBean selectByUserName(UserBean user) throws SQLException {
		return new QueryRunner(C3P0Utils.getDataSource()).query("select * from user where username=?",
				new BeanHandler<UserBean>(UserBean.class), user.getUsername());
	}

	public static void main(String[] args) {
		System.out.println(new UserDaoImpl().selectAll());
	}
	
}

        以上便是全部内容,本人也时学生,还处在学习阶段。如果您有更高的见解,或发现bug,或有更好的优化等,都欢迎您的评论,讨论,希望能和您一起进步!!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值