資料庫元資料、jdbcTemplate
資料庫元資料
什麼是元資料:
- 用來定義資料庫,資料表的資料。
JDBC中元資料的分類
三種元資料 | 如何得到元資料 |
資料庫元資料 | 通過Connection物件獲取 |
引數元資料 | 通過PreparedStatement物件獲取 |
結果集元資料 | 通過ResultSet物件獲取 |
- 所有的元資料都被封裝成了類的物件。
什麼是資料庫的元資料:
- 描述資料庫表的列名,屬性型別,結果集的資料,為了更好理解別人資料庫工具類底層的原理。
引數元資料:ParameterMetaData
ParameterMetaData物件的作用:
- 獲得佔位符問號的個數。
- 佔位符?的資料型別。
通過PrepareStatement物件的方法:
ParameterMetaData getParameterMetaData()
- 獲取ParameterMetaData物件
ParameterMetaData介面常用方法:
int getParameterCount()
- 獲得引數的個數(佔位符問號的個數)。
String getParameterTypeName(int param)
- 獲得指定位置引數的資料型別。從1開始。
- 預設情況下:因為MySQL驅動的原因,不支援得到引數元資料的型別。
示例程式碼:
public class ParamterMetaDataDemo01 { public static void main(String[] args) throws Exception { // 獲得連線物件 Connection conn = DruidDataSourceUtils.getConnection(); // 獲得預編譯物件 PreparedStatement ps = conn.prepareStatement("insert into " + "student values(null,?,?,?)"); // 給佔位符引數賦值 ps.setString(1, "⼩澤"); ps.setString(2, "⼥"); ps.setDate(3, Date.valueOf("1999-10-20")); // 獲得引數元資料物件 ParameterMetaData pmd = ps.getParameterMetaData(); // 獲得引數的個數 int count = pmd.getParameterCount(); System.out.println("引數個數:" + count); // 獲得指定位置引數的資料型別 String typeName = pmd.getParameterTypeName(3); System.out.println("引數型別:" + typeName); // 執行Sql語句 int row = ps.executeUpdate(); System.out.println(row); // 關閉資源 DruidDataSourceUtils.close(ps, conn); } }
ResultSetMetaData
ResultSetMetaData結果集元資料的作用:
- 用來獲得結果集中的列數。
- 用來獲得列的資料型別。
- 用來獲得列的名字。
通過ResultSet物件的方法:
ResultSetMetaData getMetaData()
- 獲得ResultSetMetaData物件。
ResultSetMetaData類常用方法:
int getColumnCount()
- 獲得列的數量。
String getColumnName(int column)
- 獲得指定列的列名。
String getColumnTypeName(int column)
- 獲得指定列的型別名稱。
示例程式碼:
public class ResultSetMetaDemoDemo01 {
public static void main(String[] args)throws Exception{
// 獲得連線物件
Connection conn = DruidDataSourceUtils.getConnection();
// 獲得預編譯物件
PreparedStatement ps = conn.prepareStatement("SELECT * FROM student;");
// 執行查詢操作並獲得結果集物件
ResultSet rs = ps.executeQuery();
// 獲得結果集元資料物件
ResultSetMetaData rsm = rs.getMetaData();
System.out.println("總列數:" + rsm.getColumnCount());
int colums = rsm.getColumnCount();
for (int i = 1; i <= colums; i++) {
System.out.println("列名:" + rsm.getColumnName(i));
System.out.println("列的型別:" + rsm.getColumnTypeName(i));
}
// 關閉資源
DruidDataSourceUtils.close(rs,ps,conn);
}
}
JdbcTemplate
概述:
- JdbcTemplate就是Spring對JDBC的封裝,目的是使JDBC更加易於使用。JdbcTemplate是Spring的一部分。
- 處理了資源的建立和釋放。
JdbcTemplate的好處:
- 不需要我們管理連線了。
- 不需要我們設定引數了。
- 查詢時候可以直接返回對應的實體類。
JdbcTemplate的使用步驟:
- 匯入jdbcTemplate的5個jar包。
- 建立JdbcTemplate物件,傳入Druid連線池。
- 呼叫execute、update、queryXxx等方法。
如何建立JDBCTemplate的核心類:JdbcTemplate
public JdbcTemplate( DataSource dataSource );
- 建立JdbcTemplate物件,方便執行SQL語句。
JdbcTemplate實現建立表:
public void execute( String sql );
- execute可以執行所有SQL語句,因為沒有返回值,一般用於執行DDL語句。
示例程式碼:
public class JDBCTemplateDemo01 {
public static void main(String[] args){
// 建立JDBCTemplate物件
JdbcTemplate jt = new JdbcTemplate(DruidDataSourceUtils.getDataSource());
// 執行SQL語句句
jt.execute("CREATE table product(id int primary key auto_increment," +
"pname varchar(20)," +
"price double);");
}
}
Jdbctemplate實現增刪改:
int update(String sql,Object...params);
- 用於執行增刪改等DML語句。
總結:
JdbcTemplate的update方法用於執行DML語句。同時還可以在SQL語句中使用 ?佔位,在update方法的object...args可變引數中傳入對應的引數。
JdbcTemplate實現查詢
注意事項:
- queryForObject與queryForMap如果查詢不到結果,都會出現異常。我們需要抓取異常。
- 異常是:EmptyResultDataAccessException
queryForObject查詢單個欄位
public <T> T queryForObject(String sql, Class<T> requiredType ,Object...params)
- 執行查詢語句,返回一個指定型別的資料。
引數說明:
- sql:執行的sql語句。
- requiredType:查詢結果的型別。
- params:sql需要的引數。
queryForMap查詢單個物件
public Map<String, Object> queryForMap(String sql,Object...args)
- queryForMap會把一行的資料儲存到Map物件中,一個Map物件就儲存一行記錄,key儲存的是列名,value是儲存該行資料的值。
拓展:
- 查詢多個表返回一條記錄使用Map封裝結果。
示例程式碼:
public Route findRouteByRid(String rid) throws Exception {
Map<String,Object> map = routeDao.findRouteByRid(rid);
List<RouteImg> list = routeDao.findRouteImgsByRid(rid);
Route route = new Route();
Category category = new Category();
Seller seller = new Seller();
BeanUtils.populate(route,map);
BeanUtils.populate(category,map);
BeanUtils.populate(seller,map);
route.setCategory(category);
route.setSeller(seller);
route.setRouteImgList(list);
return route;
}
public Map<String,Object> findRouteByRid(String rid) {
String sql = "SELECT * FROM tab_route r,tab_category c,tab_seller s WHERE r.`cid` = c.`cid` AND r.`sid` = s.`sid` AND r.rid = ?";
try {
Map<String, Object> map = jdbcTemplate.queryForMap(sql, rid);
return map;
} catch (DataAccessException e) {
return null;
}
}
queryForObject查詢單個物件
public <T> List<T> queryForObject(String sql, RowMapper<T> rowMapper,object...args)
- 返回指定的類。
queryForList查詢多個物件
- 適用於單表查詢,也適用於多表查詢。
public List<Map<String, Object>> queryForList(String sql,object...args)
- 執行查詢語句,返回一個List集合,List中存放的是Map型別的資料。
示例程式碼:
public List<Map<String, Object>> findFavoriteListByPage(int uid, int start, int length) throws SQLException {
String sql = "SELECT * FROM tab_favorite f,tab_route r WHERE f.`rid` = r.`rid` AND uid = ? ORDER BY f.`date` DESC LIMIT ?,?";
List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql, uid, start, length);
return mapList;
}
public PageBean<Favorite> getPageBean(int uid, String curPage) throws Exception {
int curpage = Integer.parseInt(curPage);
PageBean<Favorite> pageBean = new PageBean<>();
pageBean.setCurPage(curpage);
int pageSize = 3;
pageBean.setPageSize(pageSize);
int count = iFavoriteDao.getCount(uid);
pageBean.setCount(count);
int start = (curpage-1)*pageSize;
int length = pageSize;
List<Map<String,Object>> mapList = iFavoriteDao.findFavoriteListByPage(uid,start,length);
List<Favorite> list = null;
if(mapList!=null&&mapList.size()>0){
list = new ArrayList<>();
for (Map<String, Object> map : mapList) {
Favorite favorite = new Favorite();
Route route = new Route();
BeanUtils.populate(favorite,map);
BeanUtils.populate(route,map);
favorite.setRoute(route);
list.add(favorite);
}
}
pageBean.setDataList(list);
return pageBean;
}
query查詢多個物件,使用RowMapper做對映返回物件
- 此重寫介面的方法,適用於多表查詢,也適用於單表查詢。
public <T> List<T> query(String sql, RowMapper<T> rowMapper,object...args)
- 執行查詢語句,返回一個List集合,List中存放的是RowMapper指定型別的資料。
- RowMapper的引數寫:類名
RowMapper介面的抽象方法:
mapRow( ResultSet resultSet, int i)
- resultSet:JdbcTemplate每得到一行資料,都會直接給了resultSet物件。
- i:當前是第幾行。
在抽象方法內的具體操作:
- 建立實現類物件。
- 用ResultSet裡的值對建立的類賦值。
- 返回類物件。
示例程式碼:
@Test
public void test06() throws Exception {
// 建立JDBCTemplate物件
JdbcTemplate jt = new JdbcTemplate(DruidDataSourceUtils.getDataSource());
// 執⾏行行查詢操作
List<Product> products = jt.query("select * from product;", new
RowMapper<Product>() {
@Override
public Product mapRow(ResultSet rs, int i) throws SQLException {
// 建立產品物件
Product p = new Product();
// System.out.println("i = " + i);
p.setId(rs.getInt("id"));
p.setPname(rs.getString("pname"));
p.setPrice(rs.getDouble("price"));
return p;
}
});
for (Product product : products) {
System.out.println(product);
}
}
query查詢多個物件,使用BeanPropertyRowMapper做對映返回物件
- 此用實現類實現介面的方法,適用於單表查詢,不適用於多表查詢。
public <T> List<T> query(String sql, RowMapper<T> rowMapper,object...args)
- 執行查詢語句,返回一個List集合,List中存放的是RowMapper指定型別的資料。
- RowMapper的引數寫:類名.class
public class BeanPropertyRowMapper<T> implements RowMapper<T>
- BeanPropertyRowMapper類實現了RowMapper介面
表的欄位名與實體類屬性名對映的規則:
- 表的欄位名與類中的屬性名相同,表的欄位名大小寫不區分。
- 表的欄位名如果有多個單詞使用下劃線隔開,與java中駝峰命名的屬性相對應。
- 示例:dept_name 對應 deptName
示例程式碼:
@Test
public void test07() throws Exception {
// 建立JDBCTemplate物件
JdbcTemplate jt = new JdbcTemplate(DruidDataSourceUtils.getDataSource());
// 執行查詢操作獲得List集合
List<Product> products = jt.query("select * from product where id < ?;", new
BeanPropertyRowMapper<>(Product.class),5);
for (Product product : products) {
System.out.println(product);
}
}