连接池、Dbutils、事务、分层

每个线程操作数据库都需要创建一个连接对象,用完之后需要关闭。创建对象、关闭对象消耗系统资源大于执行sql语句消耗的资源。高并发情况下服务器可能宕机。

数据库连接池技术是解决这个问题最常用的方法,在许多应用程序服务器(例如:Weblogic,WebSphere,JBoss)中,基本都提供了这项技术,无需自己编程,但是,深入了解这项技术是非常必要的。

DBCP(DataBase connection pool)数据库连接池。是 Apache 上的一个 Java 连接池项目,也是 tomcat 使用的连接池组件。单独使用DBCP需要2个包:commons-dbcp.jar和commons-pool.jar。
由于建立数据库连接是一种非常耗时、耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个,使用完毕后归还到连接池中。

以下是,DBCP的配置文件:

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/user_password
username=root
password=Root

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000


#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

使用DBCP查询数据库:

package ink.longpress.www;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class One {
	public static void main(String[] args) throws Exception {
		
		//导入配置文件
		Properties properties = new Properties();
		properties.load(new FileInputStream("src/ink/longpress/www/dbcpconfig.properties"));
		
		//使用文件创建DataSource对象
		DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
		
		//建立数据库连接
		Connection connection = dataSource.getConnection();
		
		String sql = "select * from userinfo";
		PreparedStatement preparedStatement = connection.prepareStatement(sql);
		
		ResultSet resultSet = preparedStatement.executeQuery();
		
		while (resultSet.next()) {
			System.out.println(resultSet.getInt(1) + "\t" + resultSet.getString(2) + "\t" + resultSet.getString(3));
		}
	}
}

如此,每次都需要导入配置文件,建立连接等操作,可以建立一个工具类。

package ink.longpress.www;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DBCP {
	private static DataSource dataSource;

	// 静态代码导入配置文件,创建DataSource对象
	static {
		try {
			Properties properties = new Properties();
			properties.load(new FileInputStream("src/ink/longpress/www/dbcpconfig.properties"));
			dataSource = BasicDataSourceFactory.createDataSource(properties);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	// 静态方法,返回DataSource对象
	public static DataSource getDataSource() {
		return dataSource;
	}

	// 静态方法,返回Connection对象
	public static Connection getConnection() throws Exception {
		return dataSource.getConnection();
	}
}

使用工具类来完成查询:

package ink.longpress.www;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Two {
	public static void main(String[] args) {
		try {
			Connection connection = DBCP.getConnection();
			String sql = "select * from userinfo";
			PreparedStatement preparedStatement = connection.prepareStatement(sql);
			
			ResultSet resultSet = preparedStatement.executeQuery();
			
			while (resultSet.next()) {
				System.out.println(resultSet.getInt(1) + "\t" + resultSet.getString(2) + "\t" + resultSet.getString(3));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

C3P0连接池

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

下面是C3P0的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<!-- 默认配置,如果没有指定则使用这个配置 -->
	<default-config>
		<!-- 四项基本配置 -->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/user_password</property>
		<property name="user">root</property>
		<property name="password">root</property>
		
		<!-- 当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出
  			SQLException,如设为0则无限期等待。单位毫秒。Default: 0 -->
		<property name="checkoutTimeout">30000</property>
		
		<!--隔多少秒检查连接池的空闲连接,0表示不检查-->
		<property name="idleConnectionTestPeriod">30</property>
		
		<!-- 初始化连接数 -->
		<property name="initialPoolSize">10</property>
		
		<!-- 连接的最大空闲时间,默认为0秒、不会关闭任何连接。设置30秒,30秒到期后,
			连接若未使用就会被关闭 -->
		<property name="maxIdleTime">30</property>
		
		<!-- 池中最多的连接存放数目 -->
		<property name="maxPoolSize">100</property>
		
		<!-- 池中最少的连接存放数目 -->
		<property name="minPoolSize">10</property>
		<property name="maxStatements">200</property>
		<user-overrides user="test-user">
			<property name="maxPoolSize">10</property>
			<property name="minPoolSize">1</property>
			<property name="maxStatements">0</property>
		</user-overrides>
	</default-config>
	<!-- 命名的配置 -->
	<named-config name="offcn">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/day04_db</property>
		<property name="user">root</property>
		<property name="password">1234</property>
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">20</property>
		<property name="minPoolSize">10</property>
		<property name="maxPoolSize">40</property>
		<property name="maxStatements">0</property>
		<property name="maxStatementsPerConnection">5</property>
	</named-config>
</c3p0-config>

使用C3P0查询数据库 :

package ink.longpress.www;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Three {
	
	@Test
	public void test() {
		try {
			//使用C3P0的默认配置,配置文件需放在src文件夹下
			//读取配置文件创建连接
			ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
			Connection connection = comboPooledDataSource.getConnection();
			
			String sql = "select * from userinfo";
			PreparedStatement prepareStatement = connection.prepareStatement(sql);
			ResultSet resultSet = prepareStatement.executeQuery();
			
			while (resultSet.next()) {
				System.out.println(resultSet.getInt(1) + "\t" + resultSet.getString(2) + "\t" + resultSet.getString(3));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

C3P0也可以写一个工具类来简化代码:

package ink.longpress.www;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0 {
	
	private static DataSource dataSource = new ComboPooledDataSource();
	
	public static DataSource getDataSource() {
		return dataSource;
	}
	
	public static Connection getConnection() throws SQLException {
		return dataSource.getConnection();
	}
}

使用C3P0工具类来查询数据库:

package ink.longpress.www;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Four {
	public static void main(String[] args) throws SQLException {
		//获取连接
		Connection connection = C3P0.getConnection();
		
		String sql = "select * from userinfo";
		PreparedStatement preparedStatement = connection.prepareStatement(sql);
		ResultSet resultSet = preparedStatement.executeQuery();
		
		while (resultSet.next()) {
			System.out.println(resultSet.getInt(1) + "\t" + resultSet.getString(2) + "\t" + resultSet.getString(3));
		}
	}
}

DBUtils工具

Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。

DBUtils是java编程中的数据库操作实用工具,小巧简单实用,
1.对于数据表的读操作,他可以把结果转换成List,Array,Set等java集合,便于程序员操作;
2.对于数据表的写操作,也变得很简单(只需写sql语句)
3.可以使用数据源,使用JNDI,数据库连接池等技术来优化性能--重用已经构建好的数据库连接对象,而不像php,asp那样,费时费力的不断重复的构建和析构这样的对象。

QueryRunner:核心类,DBUtils工具的所有的操作都需要QueryRunner完成。
ResultSetHandler:结果集对象,可以将操作结果封装为一个java对象。
DBUtils:驱动管理,释放资源。

使用 DBUtils 完成数据增删改的操作

有以下数据库:

userId  userName  userpassword  
------  --------  --------------
     1  jack      abc           
     3  Queen     jack123       
     4  Jokkcc    7896586       
     5  Acer      jack123       
     6  Joker     jack123       
     7  Toker     jack123   
package ink.longpress.www;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

public class Five {
	
	//增加数据
	@Test
	public  void autoOne() throws SQLException {
		//自动模式
		QueryRunner queryRunner = new QueryRunner(C3P0.getDataSource());
		String sql = "insert into userinfo values(?,?,?)";
		Object[] objects = {null,"Pocker","zxcvbnm"};
		queryRunner.update(sql, objects);
	}
	
	//增加数据
	@Test
	public  void handOne() throws SQLException {
		//手动模式
		QueryRunner queryRunner = new QueryRunner();
		Connection connection = C3P0.getConnection();
		String sql = "insert into userinfo values(?,?,?)";
		Object[] objects = {null,"Sucks","asdfghjkl"};
		queryRunner.update(connection,sql, objects);
		DbUtils.close(connection);
	}
	
	//修改数据
	@Test
	public  void changeOne() throws SQLException {
		QueryRunner queryRunner = new QueryRunner(C3P0.getDataSource());
		String sql = "update userinfo set userpassword = ? where username = ?";
		Object[] objects = {"Sucks","Sucks"};
		queryRunner.update(sql, objects);
	}
	
	//删除数据
	@Test
	public  void deleteOne() throws SQLException {
		QueryRunner queryRunner = new QueryRunner(C3P0.getDataSource());
		String sql = "delete from userinfo where userid = ?";
		queryRunner.update(sql, 4);
	}
}

运行完成后:

userId  userName  userpassword  
------  --------  --------------
     1  jack      abc           
     3  Queen     jack123       
     5  Acer      jack123       
     6  Joker     jack123       
     7  Toker     jack123       
     8  Pocker    zxcvbnm       
     9  Sucks     Sucks         

使用DBUtils核心类完成数据查询操作

package ink.longpress.www;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.junit.Test;

public class Six {
	@Test
	public void searchOne() throws SQLException {
		QueryRunner queryRunner = new QueryRunner(C3P0.getDataSource());
		String sql = "select * from userinfo where userid = ?";
		// 使用QueryRunner的query方法
		UserInfo userInfo = queryRunner.query(sql, new ResultSetHandler<UserInfo>() {
			@Override
			public UserInfo handle(ResultSet resultSet) throws SQLException {
				while (resultSet.next()) {
					int int1 = resultSet.getInt("userid");
					String string = resultSet.getString(2);
					String string2 = resultSet.getString(3);
					return new UserInfo(int1, string, string2);
				}
				return null;
			}
		}, 1);
		System.out.println(userInfo);
	}

	@Test
	public void searchAll() throws SQLException {
		QueryRunner queryRunner = new QueryRunner(C3P0.getDataSource());
		String sql = "select * from userinfo";
		// 使用QueryRunner的query方法
		List<UserInfo> userInfoList = queryRunner.query(sql, new ResultSetHandler<List<UserInfo>>() {
			@Override
			public List<UserInfo> handle(ResultSet resultSet) throws SQLException {
				List<UserInfo> list = new ArrayList<UserInfo>();
				while (resultSet.next()) {
					int int1 = resultSet.getInt("userid");
					String string = resultSet.getString(2);
					String string2 = resultSet.getString(3);
					list.add(new UserInfo(int1, string, string2));
				}
				return list;
			}
		});
		System.out.println(userInfoList);
	}
}
package ink.longpress.www;

public class UserInfo {
	private int userID;
	private String userName;
	private String userpassword;
	public UserInfo() {
		super();
	}
	public UserInfo(int userID, String userName, String userpassword) {
		super();
		this.userID = userID;
		this.userName = userName;
		this.userpassword = userpassword;
	}
	public int getUserID() {
		return userID;
	}
	public void setUserID(int userID) {
		this.userID = userID;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserpassword() {
		return userpassword;
	}
	public void setUserpassword(String userpassword) {
		this.userpassword = userpassword;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		UserInfo other = (UserInfo) obj;
		if (userID != other.userID)
			return false;
		if (userName != other.userName)
			return false;
		if (userpassword != other.userpassword)
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "UserInfo [userID=" + userID + ", userName=" + userName + ", userpassword=" + userpassword + "]";
	}
}

以上方法每次都需要定义实例类,可以使用定义好的接口, ResultSetHandler  结果集处理程序

BeanHandler 将查询结果的第一条封装到一个javaBean对象中
BeanListHandler 将每一条查询结果封装到一个javaBean对象中,所有的javaBean对象保存到List集合中
MapHandler 将查询结果的第一条封装到一个map<String key Object value,>集合中. Key就是字段名,value就是字段值。
MapListHandler 将查询结果的每一条封装到一个map<String key Object value,>集合中。 将所有的map集合封装到list集合中。
ScalarHandler 获取查询单一结果的值。Select count(*) from product;

JavaBean

JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。众所周知,属性名称符合这种模式,其他Java 类可以通过反射机制发现和操作这些JavaBean 的属性。

BeanHandler 、BeanListHandler、MapHandler、MapListHandler、ScalarHandler使用案例:

有以下数据库:

userId  userName  userpassword  
------  --------  --------------
     1  jack      abc           
     3  Queen     jack123       
     5  Acer      jack123       
     6  Joker     jack123       
     7  Toker     jack123       
     8  Pocker    zxcvbnm       
     9  Sucks     Sucks         
package ink.longpress.www;

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

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;

public class Seven {
	// 成员变量,获取数据源
	QueryRunner queryRunner = new QueryRunner(C3P0.getDataSource());

	@Test
	public void searchBeanHandler() throws Exception {
		String sql = "select * from userinfo where userid = ?";
		// 通过反射获取UserInfo对象
		UserInfo userInfo = queryRunner.query(sql, new BeanHandler<UserInfo>(UserInfo.class), 1);
		System.out.println(userInfo);
	}

	@Test
	public void searchBeanListHandler() throws SQLException {

		String sql = "select * from userinfo";
		// 返回一个List集合
		List<UserInfo> list = queryRunner.query(sql, new BeanListHandler<UserInfo>(UserInfo.class));
		System.out.println(list);
	}

	@Test
	public void searchMapHandler() throws SQLException {

		String sql = "select * from userinfo";
		Map<String, Object> map = queryRunner.query(sql, new MapHandler());
		System.out.println(map);
	}

	@Test
	public void searchMapListHandler() throws SQLException {

		String sql = "select * from userinfo";
		List<Map<String, Object>> list = queryRunner.query(sql, new MapListHandler());
		System.out.println(list);
	}

	@Test
	public void searchScalarHandler() throws SQLException {
		String sql = "select count(*) from userinfo";
		Object query = queryRunner.query(sql, new ScalarHandler());
		System.out.println(query);
	}
}

事务

指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)由多个sql语句组成,必须作为一个整体执行。
这些sql语句作为一个整体一起向系统提交,要么都执行、要么都不执行。

MYSQL 事务处理主要有两种方法:

1、用 BEGIN, ROLLBACK, COMMIT来实现

  • BEGIN 开始一个事务
  • ROLLBACK 事务回滚
  • COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:

  • SET AUTOCOMMIT=0 禁止自动提交
  • SET AUTOCOMMIT=1 开启自动提交

事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

事务默认自动提交,如需手动提交需关闭自动提交。

Start transaction 开启事务
commit 提交事务
rollback 回滚事务

SQL语句中的事务提交:

userID  userName  userBalance  
------  --------  -------------
 10000  张三                  500
 10001  李四                 1000
#事务开始前查询
SELECT *FROM bank;
#开启事务
START TRANSACTION;
UPDATE bank SET balance=balance+1000 WHERE `name` = '张三';
UPDATE bank SET balance=balance-1000 WHERE `name` = '李四';
#转账过程中查询
SELECT * FROM bank;
#rollback;回滚
COMMIT;
#事务结束后查询
SELECT * FROM bank;

JDBC使用事务:

Conn. setAutoCommit (false) 停止自动提交,启动手动提交
Conn.commit() 提交
Conn.rollback() 回滚
package ink.longpress.www;

import java.sql.Connection;

import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

public class Eight {
	
	@Test
	public void test01() throws Exception{
		QueryRunner qr = new QueryRunner();
		Connection conn = C3P0.getConnection();
//		关闭自动提交
		conn.setAutoCommit(false);
		String sql = "UPDATE bank SET balance=balance+1000 WHERE `name` = '张三'";
		qr.update(conn, sql);
		String sql2 = "UPDATE bank SET balance=balance-1000 WHERE `name` = '李四'";
		qr.update(conn, sql2);
//		conn.rollback();
		conn.commit();
		DbUtils.close(conn);
	}
}

分层

常见得分层结构,一般为三层
Web层:表示层,
Service层:业务逻辑层,
Dao层:数据库操作层。

在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。
这也是Java Web中重要的三层架构中的三个层次。区分层次的目的即为了“高内聚低耦合”的思想。所谓三层体系结构,是在客户端与数据库之间加入了一个“中间层”,也叫组件层。这里所说的三层体系,不是指物理上的三层,不是简单地放置三台机器就是三层体系结构,也不仅仅有B/S应用才是三层体系结构,三层是指逻辑上的三层,即把这三个层放置到一台机器上。

分层的优点:
1:方便后期维护。
2:提高代码复用性。
3:解耦

分层示例:

ink.longpress.dao:数据访问层
ink.longpress .service:业务逻辑层
ink.longpress.web:表示层
ink.longpress.utils:工具类
ink.longpress.domain:实体类。

使用分层思想写一个查账记账的示例:

先向数据库中添加一些数据:

CREATE DATABASE Bookkeeping CHARSET utf8;

USE Bookkeeping;

CREATE TABLE records (
  zwid INT PRIMARY KEY AUTO_INCREMENT,
  flname VARCHAR(200),
  money DOUBLE,
  zhangHu VARCHAR(100),
  createtime DATE,
  description VARCHAR(1000)
);

INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (1,'吃饭支出',247,'交通银行','2016-03-02','家庭聚餐');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (2,'工资收入',12345,'现金','2016-03-15','开工资了');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (3,'服装支出',1998,'现金','2016-04-02','买衣服');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (4,'吃饭支出',325,'现金','2016-06-18','朋友聚餐');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (5,'股票收入',8000,'工商银行','2016-10-28','股票大涨');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (6,'股票收入',5000,'工商银行','2016-10-28','股票又大涨');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (7,'工资收入',5000,'交通银行','2016-10-28','又开工资了');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (8,'礼金支出',5000,'现金','2016-10-28','朋友结婚');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (9,'其他支出',1560,'现金','2016-10-29','丢钱了');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (10,'交通支出',2300,'交通银行','2016-10-29','油价还在涨啊');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (11,'吃饭支出',1000,'工商银行','2016-10-29','又吃饭');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (12,'工资收入',1000,'现金','2016-10-30','开资');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (13,'交通支出',2000,'现金','2016-10-30','机票好贵');
INSERT  INTO records(zwid,flname,money,zhangHu,createtime,description) VALUES (14,'工资收入',5000,'现金','2016-10-30','又开资');

SELECT * FROM records;
  zwid  flname         money  zhangHu       createtime  description         
------  ------------  ------  ------------  ----------  --------------------
     1  吃饭支出             247  交通银行          2016-03-02  家庭聚餐        
     2  工资收入           12345  现金            2016-03-15  开工资了        
     3  服装支出            1998  现金            2016-04-02  买衣服           
     4  吃饭支出             325  现金            2016-06-18  朋友聚餐        
     5  股票收入            8000  工商银行          2016-10-28  股票大涨        
     6  股票收入            5000  工商银行          2016-10-28  股票又大涨     
     7  工资收入            5000  交通银行          2016-10-28  又开工资了     
     8  礼金支出            5000  现金            2016-10-28  朋友结婚        
     9  其他支出            1560  现金            2016-10-29  丢钱了           
    10  交通支出            2300  交通银行          2016-10-29  油价还在涨啊  
    11  吃饭支出            1000  工商银行          2016-10-29  又吃饭           
    12  工资收入            1000  现金            2016-10-30  开资              
    13  交通支出            2000  现金            2016-10-30  机票好贵        
    14  工资收入            5000  现金            2016-10-30  又开资           

jingsongchan

发表评论

电子邮件地址不会被公开。 必填项已用*标注