数据库元数据
什么是元数据:
- 用来定义数据库,数据表的数据。
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);
}
}