如果数据库字段和 ORM 实体类属性不一致,可以用 .properties 文件做映射。注意,测试时最好别改数据库字段,改实体类属性字段就行。
在 src 下创建 jdbc.properties。修改 Account 类。
// jdbc.properties
uname=name
money=balance
// Account 类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {
private Integer id;
private String uname;
private String password;
private double money;
}
在 DBUtils 里对 Properties 做简单封装。
public class DBUtils {
public static Properties properties = new Properties();
static {
try {
properties.load(DBUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static Properties getProperties() {
return properties;
}
修改 DaoUtils 类。捕获数据库取值异常。
public class DaoUtils {
// 更新操作
public static int commonUpdate(String sql, Object ...args) {
Connection connection = DBUtils.getConnection();
PreparedStatement prst = null;
try {
prst = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i ++) {
prst.setObject(i + 1,args[i]);
}
return prst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.close(prst);
}
return 0;
}
// 查询操作
public static <T>List<T> commonQuery(String sql, Class<T> cls, Object ...args) {
Connection connection = DBUtils.getConnection();
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
Account account = null; // 声明
List<T> list = new ArrayList<>();
try {
preparedStatement = connection.prepareStatement(sql);
if (args!=null && args.length > 0) {
for (int i = 0;i< args.length;i ++) {
preparedStatement.setObject(i + 1,args[i]);
}
}
resultSet = preparedStatement.executeQuery();
// 反射 获取类中所有属性
Field[] fields = cls.getDeclaredFields();
while (resultSet.next()) {
// 反射对象
T o = cls.newInstance();
for (int i = 0; i < fields.length; i ++) {
// 遍历属性名
String fieldName = fields[i].getName();
// 根据字段名获取结果集中数据库数据
Object object = null;
try {
// 根据属性名从数据库取值
object = resultSet.getObject(fieldName);
} catch (SQLException e) {
System.out.println("字段不一致");
Properties properties = DBUtils.getProperties();
String newValue = properties.getProperty(fieldName);
object = resultSet.getObject(newValue);
}
// 给私有属性赋值权限
fields[i].setAccessible(true);
fields[i].set(o, object);
}
list.add(o);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} finally {
DBUtils.close(connection, preparedStatement, resultSet);
}
return list;
}
}
Druid 连接池。在程序初始化时,预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时,从连接池中取出现有连接;使用完毕后,也不会进行关闭,而是放回池中,实现复用,节省资源。
工程中加入 druid-1.1.5.jar, jdbc.properties 加入配置项。
// jdbc.properties
#连接设置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb1?characterEncoding=utf-8
username=root
password=Liu01234
#初始化可连接数量,实际项目时要设置更大值
initialSize=100
#最大连接数量
maxActive=500
#最小空闲连接,当空闲连接小于此值时会开辟新当空间,直到最大连接数量
minIdle=50
#超时等待时间以毫秒为单位 1000等于1秒
maxWait=5000
DBUtils 里使用 DruidDataSource。注意 Connection 还是需要放入 ThreadLocal, 保证同一线程是同一个连接。
public class DBUtils {
// 创建一个数据源
private static DruidDataSource dataSource = null;
private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
public static Properties properties = new Properties();
static {
try {
properties.load(DBUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
// 实例化连接池
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
dataSource.removeAbandoned();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Properties getProperties() {
return properties;
}
public static Connection getConnection() {
Connection connection = threadLocal.get();
if (connection == null ) {
try {
threadLocal.set(dataSource.getConnection());
connection = threadLocal.get();
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.println("connection = " + connection );
return connection;
}
Druid 连接池管理的 connection 不用主动关闭,否则会报 connection holder is null 的错误。
Apache的DbUtils使用。加入 commons-dbutils-1.7.jar。
public class OrmDemo {
public static void main(String[] args) throws IOException, SQLException {
QueryRunner queryRunner = new QueryRunner(DBUtils.dataSource);
Connection connection = DBUtils.dataSource.getConnection();
connection.setAutoCommit(false);
try {
int j = queryRunner.update(connection,"update t_account set balance = balance - ? where username = ?", 100, "李四");
System.out.println(j);
// int i = 10/0;
int x = queryRunner.update(connection,"update t_account set balance = balance + ? where username = ?", 100, "张三");
System.out.println(x);
connection.commit();
}catch (Exception e){
System.out.println("出现异常了");
connection.rollback();
}finally {
DBUtils.close(connection);
}
// 查询 1, 数据库列下标从 1 开始, id 序号
Account account = queryRunner.query("select * from t_account where id = ?", new BeanHandler<Account>(Account.class), 1);
System.out.println(account);
// 查询
List<Account> accountList= queryRunner.query("select * from t_account", new BeanListHandler<Account>(Account.class));
System.out.println(accountList);
}
}