package com.csdn.mymvc.dao;
import com.alibaba.druid.pool.DruidDataSource;
import com.csdn.mymvc.util.ClassUtil;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public abstract class BaseDao {
private String entityClassName;
public BaseDao() {
// this 是谁? this代表的是 FruitDaoImpl 的实例对象,因为 BaseDao是抽象类,不能直接创建对象,所以 new 的是它的子类对象 FruitDaoImpl
// this.getClass() 获取的是 FruitDaoImpl 的Class对象
// getGenericSuperclass() 获取到的是:BaseDao
// Type 是顶层接口,表示所有的类型。它有一个子接口:ParameterizedType
ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
// Actual:实际的
// getActualTypeArguments() 获取实际的类型参数
Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
Type actualTypeArgument = actualTypeArguments[0];
// System.out.println(actualTypeArgument.getTypeName());//com.csdn.fruit.pojo.Fruit
entityClassName = actualTypeArgument.getTypeName();
initDataSource();
}
private DataSource dataSource;
//加载jdbc.properties文件
private void initDataSource() {
try {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(inputStream);
String driver = properties.getProperty("jdbc.driver", "com.mysql.cj.jdbc.Driver");
String url = properties.getProperty("jdbc.url", "jdbc:mysql:///fruitdb");
String user = properties.getProperty("jdbc.user", "root");
String pwd = properties.getProperty("jdbc.pwd", "123456");
Integer initSize = Integer.parseInt(properties.getProperty("jdbc.init_size", "5"));
Integer maxActive = Integer.parseInt(properties.getProperty("jdbc.max_active", "10"));
Integer maxWait = Integer.parseInt(properties.getProperty("jdbc.max_wait", "5000"));
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(user);
druidDataSource.setPassword(pwd);
druidDataSource.setInitialSize(initSize);
druidDataSource.setMaxActive(maxActive);
druidDataSource.setMaxWait(maxWait);
dataSource = druidDataSource;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private Connection getConn() throws SQLException {
return dataSource.getConnection();
}
private void close(Connection conn, PreparedStatement psmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (psmt != null) {
psmt.close();
}
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//抽取执行更新方法
//执行更新,返回影响行数
//如果是执行 insert,那么可以尝试返回自增列的值
protected int executeUpdate(String sql, Object... params) {
boolean insertFlag = sql.trim().toUpperCase().startsWith("INSERT");
Connection conn = null;
PreparedStatement psmt = null;
try {
conn = getConn();
psmt = insertFlag ? conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : conn.prepareStatement(sql);
setParams(psmt, params);
int count = psmt.executeUpdate();
if (insertFlag) {
ResultSet rs = psmt.getGeneratedKeys();
if (rs.next()) {
Long id = rs.getLong(1);
count = id.intValue();
}
}
return count;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
close(conn, psmt, null);
}
}
//设置参数
private void setParams(PreparedStatement psmt, Object... params) throws SQLException {
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
psmt.setObject(i + 1, params[i]);
}
}
}
//执行查询,返回集合
protected List executeQuery(String sql, Object... params) {
List list = new ArrayList<>();
Connection conn = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
conn = getConn();
psmt = conn.prepareStatement(sql);
setParams(psmt, params);
rs = psmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();//元数据,结果集的结构数据
while (rs.next()) {
//T t = new T(); T仅仅是一个符号,所以不能 new
T t = (T) ClassUtil.createInstance(entityClassName);
int columnCount = rsmd.getColumnCount();//获取结果集的列的数据
//jdbc中都是从 1 开始,所以要把 i 改成 从 1 开始
for (int i = 1; i <= columnCount; i++) {
//假设循环 5 次,得到 5 个值,应该对应的是一个对象的 5 个属性的值
String columnName = rsmd.getColumnLabel(i);
Object columnValue = rs.getObject(i);
//给 t 这个对象的 columnName 属性赋 columnValue 值
ClassUtil.setProperty(t, columnName, columnValue);
}
list.add(t);
}
return list;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
close(conn, psmt, rs);
}
}
protected T load(String sql, Object... params) {
Connection conn = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
conn = getConn();
psmt = conn.prepareStatement(sql);
setParams(psmt, params);
rs = psmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();//元数据,结果集的结构数据
if (rs.next()) {
//T t = new T(); T仅仅是一个符号,所以不能 new
T t = (T) ClassUtil.createInstance(entityClassName);
int columnCount = rsmd.getColumnCount();//获取结果集的列的数据
//jdbc中都是从 1 开始,所以要把 i 改成 从 1 开始
for (int i = 1; i <= columnCount; i++) {
//假设循环 5 次,得到 5 个值,应该对应的是一个对象的 5 个属性的值
String columnName = rsmd.getColumnLabel(i);
Object columnValue = rs.getObject(i);
//给 t 这个对象的 columnName 属性赋 columnValue 值
ClassUtil.setProperty(t, columnName, columnValue);
}
return t;
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
close(conn, psmt, rs);
}
return null;
}
//select max(age) as max_age , avg(age) as avg_age from t_user
// 28 24.5
//select deptNo,avg(sal) as avg_sal from emp group by deptNo
/**
* d001 3500
* d002 3650
* d003 2998
*/
protected List
7、 设计Class工具类
package com.csdn.mymvc.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ClassUtil {
public static Object createInstance(String entityClassName) {
try {
return Class.forName(entityClassName).getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException |
ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public static void setProperty(Object instance, String propertyName, Object propertyValue) {
Class> aClass = instance.getClass();
try {
Field field = aClass.getDeclaredField(propertyName);
field.setAccessible(true);
field.set(instance, propertyValue);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
8、测试DAO层实现类
package com.csdn.dao.impl;
import com.csdn.fruit.dao.FruitDao;
import com.csdn.fruit.dao.impl.FruitDaoImpl;
import com.csdn.fruit.pojo.Fruit;
import org.junit.Test;
import java.util.List;
public class FruitDaoImplTest {
private FruitDao fruitDao = new FruitDaoImpl();
@Test
public void testAddFruit() {
Fruit fruit = new Fruit("香蕉", 7, 77, "波罗蜜是一种神奇的水果!");
fruitDao.addFruit(fruit);
}
@Test
public void testDelFruit() {
fruitDao.delFruit("哈密瓜");
}
@Test
public void testUpdateFruit() {
Fruit fruit = new Fruit("波罗蜜", 5, 1000, "好吃");
fruitDao.updateFruit(fruit);
}
@Test
public void testGetFruitList() {
List fruitList = fruitDao.getFruitList();
fruitList.stream().forEach(System.out::println);
}
@Test
public void testGetFruitByFname() {
Fruit fruit = fruitDao.getFruitByFname("波罗蜜");
System.out.println(fruit);
}
/*
// this 是谁? this代表的是 FruitDaoImpl 的实例对象,因为 BaseDao是抽象类,不能直接创建对象,所以 new 的是它的子类对象 FruitDaoImpl
// this.getClass() 获取的是 FruitDaoImpl 的Class对象
// getGenericSuperclass() 获取到的是:BaseDao
// Type 是顶层接口,表示所有的类型。它有一个子接口:ParameterizedType
ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
// Actual:实际的
// getActualTypeArguments() 获取实际的类型参数
Type[] actualTypeArguments = genericSuperclass.getActualTypeArguments();
Type actualTypeArgument = actualTypeArguments[0];
// System.out.println(actualTypeArgument.getTypeName());//com.csdn.fruit.pojo.Fruit
entityClassName = actualTypeArgument.getTypeName();
loadJdbcProperties();
*/
@Test
public void testActualTypeArgument() {
//这个方法是用来测试 actualTypeArgument 实际返回的参数
}
}
9、设计控制台操作菜单
package com.csdn.fruit.view;
import com.csdn.fruit.dao.FruitDao;
import com.csdn.fruit.dao.impl.FruitDaoImpl;
import com.csdn.fruit.pojo.Fruit;
import java.util.List;
import java.util.Scanner;
public class Menu {
Scanner input = new Scanner(System.in);
private FruitDao fruitDao = new FruitDaoImpl();
//显示主菜单
public int showMainMenu() {
System.out.println("================欢迎使用水果库存系统===================");
System.out.println("1.显示库存列表");
System.out.println("2.添加库存记录");
System.out.println("3.查看特定库存");
System.out.println("4.水果下架");
System.out.println("5.退出");
System.out.println("====================================================");
System.out.print("请选择:");
return input.nextInt();
}
//显示库存列表
public void showFruitList() {
List fruitList = fruitDao.getFruitList();
System.out.println("----------------------------------------------------");
System.out.println("名称\t\t单价\t\t库存\t\t备注");
if (fruitList == null || fruitList.size() <= 0) {
System.out.println("对不起,库存为空!");
} else {
/* fruitList.forEach(new Consumer() {
@Override
public void accept(Fruit fruit) {
System.out.println(fruit);
}
});*/
//fruitList.forEach(fruit -> System.out.println(fruit));
fruitList.forEach(System.out::println);
}
System.out.println("----------------------------------------------------");
}
//添加库存记录
public void addFruit() {
System.out.print("请输入水果名称:");
String fname = input.next();
Fruit fruit = fruitDao.getFruitByFname(fname);
if (fruit == null) {
System.out.print("请输入水果单价:");
Integer price = input.nextInt();
System.out.print("请输入水果库存:");
Integer fcount = input.nextInt();
System.out.print("请输入水果备注:");
String remark = input.next();
fruit = new Fruit(fname, price, fcount, remark);
fruitDao.addFruit(fruit);
} else {
System.out.print("请输入追加的库存量:");
Integer fcount = input.nextInt();
fruit.setFcount(fruit.getFcount() + fcount);
fruitDao.updateFruit(fruit);
}
System.out.println("添加成功!");
}
//查看特定库存记录
public void showFruitInfo() {
System.out.print("请输入水果名称:");
String fname = input.next();
Fruit fruit = fruitDao.getFruitByFname(fname);
if (fruit == null) {
System.out.println("对不起,没有找到对应的库存记录!");
} else {
System.out.println("----------------------------------------------------");
System.out.println("名称\t\t单价\t\t库存\t\t备注");
System.out.println(fruit);
System.out.println("----------------------------------------------------");
}
}
//水果下架
public void delFruit() {
System.out.print("请输入水果名称:");
String fname = input.next();
Fruit fruit = fruitDao.getFruitByFname(fname);
if (fruit == null) {
System.out.println("对不起,没有找到需要下架的库存记录!");
} else {
System.out.print("是否确认下架?(Y/N)");
String confirm = input.next();
if ("y".equalsIgnoreCase(confirm)) {
fruitDao.delFruit(fname);
}
}
}
//退出
public boolean exit() {
System.out.print("是否确认退出?(Y/N)");
String confirm = input.next();
boolean flag= !"y".equalsIgnoreCase(confirm);
return flag;
}
}
10、设计客户端
package com.csdn.fruit.view;
public class Client {
public static void main(String[] args) {
Menu m = new Menu();
boolean flag = true;
while (flag) {
int slt = m.showMainMenu();
switch (slt) {
case 1:
m.showFruitList();
break;
case 2:
m.addFruit();
break;
case 3:
m.showFruitInfo();
break;
case 4:
m.delFruit();
break;
case 5:
//方法设计时是否需要返回值,依据是:是否在调用的地方需要留下一些值用于再运算
flag = m.exit();
break;
default:
System.out.println("你不按套路出牌!");
break;
}
}
System.out.println("谢谢使用!再见!");
}
}
Enum是计算机编程语言中的一种数据类型---枚举类型。 在实际问题中,有些变量的取值被限定在一个有限的范围内。 例如,一个星期内只有七天 我们通常这样实现上面的定义:
public String monday;
public String tuesday;
public String wensday;
public String thursday
java.lang.IllegalStateException: No matching PlatformTransactionManager bean found for qualifier 'add' - neither qualifier match nor bean name match!
网上找了好多的资料没能解决,后来发现:项目中使用的是xml配置的方式配置事务,但是
原文:http://stackoverflow.com/questions/15585602/change-limit-for-mysql-row-size-too-large
异常信息:
Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAM
/**
* 格式化时间 2013/6/13 by 半仙 [email protected]
* 需要 pad 函数
* 接收可用的时间值.
* 返回替换时间占位符后的字符串
*
* 时间占位符:年 Y 月 M 日 D 小时 h 分 m 秒 s 重复次数表示占位数
* 如 YYYY 4占4位 YY 占2位<p></p>
* MM DD hh mm
在使用下面的命令是可以通过--help来获取更多的信息1,查询当前目录文件列表:ls
ls命令默认状态下将按首字母升序列出你当前文件夹下面的所有内容,但这样直接运行所得到的信息也是比较少的,通常它可以结合以下这些参数运行以查询更多的信息:
ls / 显示/.下的所有文件和目录
ls -l 给出文件或者文件夹的详细信息
ls -a 显示所有文件,包括隐藏文
Spring Tool Suite(简称STS)是基于Eclipse,专门针对Spring开发者提供大量的便捷功能的优秀开发工具。
在3.7.0版本主要做了如下的更新:
将eclipse版本更新至Eclipse Mars 4.5 GA
Spring Boot(JavaEE开发的颠覆者集大成者,推荐大家学习)的配置语言YAML编辑器的支持(包含自动提示,