本文查阅方法:
一、查阅目录 —— 查阅本文目录,肯定想要查阅的目录标题
二、快捷“查找” —— 在当前浏览器页面,按键 “Ctrl+F” 按键组合,开启浏览器的查找功能,
在查找搜索框中 输入须要查阅的 目录标题,即可以直接到达 标题内容 的位置。
三、学习小结 —— 文中的学习小结内容,是笔者在学习以后总结出的,开发时可直接参考其进行应用开发的内容, 进一步加快了本文的查阅 速度。(水平有限,仅供参考。)
java
本文目录sql
学习小结数据库
一、自定义JDBC框架 ——数据库元数据:DataBaseMetaDataapache
二、自定义JDBC框架 ——数据库元数据:DataBaseMetaData数组
三、自定义JDBC框架 ——结果集元数据: ResultSetMetaData浏览器
四、使用元数据简化JDBC代码app
(1) 万能更新框架
(2) 万能查询工具
五、Apache—DBUtils框架简介性能
六、DbUtils类 介绍
七、QueryRunner类 介绍
八、QueryRunner类的主要方法
九、ResultSetHandler接口 介绍
十、ResultSetHandler 接口的实现类
十一、JDBC应用的事务管理(ThreadLocal类)
十二、JDBC应用的事务管理——采用跨层跨层传递方法参数
1三、JDBC应用的事务管理—— ThreadLocal 绑定链接
1四、使用JDBC操做多个表
1五、使用JDBC操做多个表—— “一对多”关系
1六、使用JDBC操做多个表—— 多对多关系
1七、数据库端——表关系间的级联操做
相关学习
JDBC 学习笔记(一)—— 基础知识 + 分页技术
连接地址:http://even2012.iteye.com/blog/1886946
JDBC 学习笔记(二)—— 大数据+存储过程+批处理+事务
连接地址:http://even2012.iteye.com/blog/1886950
JDBC 学习笔记(三)—— 数据源(数据库链接池):DBCP数据源、C3P0 数据源以及自定义数据源技术
连接地址:http://even2012.iteye.com/blog/1886953
JDBC 学习笔记(四)—— 自定义JDBC框架+Apache—DBUtils框架+事务管理+操做多表
连接地址:http://even2012.iteye.com/blog/1886956
学习小结
一、自定义JDBC框架 ——数据库元数据:DataBaseMetaData
元数据:数据库、表、列的定义信息。
DataBaseMetaData connection.getDatabaseMetaData()
得到表明DataBaseMetaData 对象元数据的DataBaseMetaData 对象。
DataBaseMetaData对象中的方法:
(1) getURL():返回一个String类对象,表明数据库的URL。
(2) getUserName():返回链接当前数据库管理系统的用户名。
(3) getDatabaseProductName():返回数据库的产品名称。
(4) getDatabaseProductVersion():返回数据库的版本号。
(5) getDriverName():返回驱动驱动程序的名称。
(6) getDriverVersion():返回驱动程序的版本号。
(7) isReadOnly():返回一个boolean值,指示数据库是否只容许读操做。
Demo样例: 获取数据库的元数据
public void test1() throws SQLException{
Connection conn = JdbcUtils_C3P0.getConnection();
DatabaseMetaData meta = conn.getMetaData();
System.out.println(meta.getDatabaseProductName());
System.out.println(meta.getDatabaseMajorVersion());
System.out.println(meta.getDatabaseMinorVersion());
}
二、自定义JDBC框架 ——数据库元数据:DataBaseMetaData
ParameterMetaData PreparedStatement . getParameterMetaData()
得到表明PreparedStatement元数据的ParameterMetaData对象。
例如:SQL语句 “ Select * from user where name=? And password=? ” 中的两个“ ?” 问号。
ParameterMetaData对象 中的方法:
(1) getParameterCount() --得到指定参数的个数
(2) getParameterType(int param) -- 得到指定参数的sql类型(Mysql数据库不支持该方法,会报异常。)
Demo样例:参数元数据
public void test2() throws SQLException{
Connection conn = JdbcUtils_C3P0.getConnection();
String sql = "insert into user(id,name) values(?,?)";
PreparedStatement st = conn.prepareStatement(sql);
ParameterMetaData meta = st.getParameterMetaData();
System.out.println(meta.getParameterCount());
System.out.println(meta.getParameterType(1));
}
三、自定义JDBC框架 ——结果集元数据: ResultSetMetaData
ResultSetMetaData ResultSet. getMetaData()
得到表明ResultSet对象元数据的ResultSetMetaData对象。
ResultSetMetaData对象中的方法
(1) getColumnCount() -- 返回resultset对象的列数
(2) getColumnName(int column) -- 得到指定列的名称
(3) getColumnTypeName(int column) -- 得到指定列的类型
Demo样例: 结果集元数据
public void test3() throws SQLException{
Connection conn = JdbcUtils_C3P0.getConnection();
String sql = "select * from account";
PreparedStatement st = conn.prepareStatement(sql);
ResultSet rs = st.executeQuery();
ResultSetMetaData meta = rs.getMetaData();
System.out.println(meta.getColumnCount());
System.out.println(meta.getColumnName(1));
System.out.println(meta.getColumnName(2));
System.out.println(meta.getColumnName(3));
}
四、使用元数据简化JDBC代码
业务背景:系统中全部实体对象都涉及到基本的CRUD操做:
(1) 万能更新
全部实体的CUD操做代码基本相同,仅仅发送给数据库的SQL语句不一样而已,所以能够把CUD操做的全部相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句。
Demo样例1:万能更新的方法内容部分
public static void update(String sql,Object params[]) throws SQLException{
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = getConnection();
st = conn.prepareStatement(sql);
for(int i=0;i<params.length;i++){
st.setObject(i+1,params[i]);
}
st.executeUpdate();
}finally{
release(conn, st, rs);
}
}
Demo样例2:万能更新方法的调用代码
public class CustomerDaoImpl implements CustomerDao {
public void add(Customer c){
try{
String sql = "insert into customer(id,name,gender,birthday,cellphone,email,preference,type,description) values(?,?,?,?,?,?,?,?,?)";
Object params[] = {c.getId(),c.getName(),c.getGender(),c.getBirthday(),c.getCellphone(),c.getEmail(),c.getPreference(),c.getType(),c.getDescription()};
JdbcUtils.update(sql, params);
}catch (Exception e) {
throw new DaoException(e);
}
}
public void update(Customer c){ //id
try{
String sql = "update customer set name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=? where id=?";
Object params[] = {c.getName(),c.getGender(),c.getBirthday(),c.getCellphone(),c.getEmail(),c.getPreference(),c.getType(),c.getDescription(),c.getId()};
JdbcUtils.update(sql, params);
}catch (Exception e) {
throw new DaoException(e);
}
}
public void delete(String id){
try{
String sql = "delete from customer where id=?";
Object params[] = {id};
JdbcUtils.update(sql, params);
}catch (Exception e) {
throw new DaoException(e);
}
}
}
(2) 万能查询
实体的R操做,除SQL语句不一样以外,根据操做的实体不一样,对ResultSet的映射也各不相同,所以可义一个query方法,除以参数形式接收变化的SQL语句外,可使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中。
备注:关于自定义万能查询的代码,涉及到自定义处理器等代码,上面所述的数据库元数据的各类知识也都应用到其中,故有些复杂,不便学习。有万能查询需求的请学习Apache—DBUtils框架 中的查询方法部分,相对来讲只要会调用便可,学习成本会小一些。
五、Apache—DBUtils框架简介
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,而且使用dbutils能极大简化jdbc编码的工做量,同时也不会影响程序的性能。所以dbutils成为不少不喜欢hibernate的公司的首选。
工具类: org.apache.commons.dbutils.DbUtils。
API介绍:
(1) org.apache.commons.dbutils.QueryRunner
(2) org.apache.commons.dbutils.ResultSetHandler
六、DbUtils类 介绍
DbUtils :提供如关闭链接、装载JDBC驱动程序等常规工做的工具类,里面的全部方法都是静态的。主要方法以下:
(1) public static void close(…) throws java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是否是NULL,若是不是的话,它们就关闭Connection、Statement和ResultSet。
(2) public static void closeQuietly(…): 这一类方法不只能在Connection、Statement和ResultSet为NULL状况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
(3) public static void commitAndCloseQuietly(Connection conn): 用来提交链接,而后关闭链接,而且在关闭链接时不抛出SQL异常。
(4) public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,若是成功就返回true。使用该方法,你不须要捕捉这个异常ClassNotFoundException。
七、QueryRunner类 介绍
该类简单化了SQL查询,它与ResultSetHandler组合在一块儿使用能够完成大部分的数据库操做,可以大大减小编码量。
QueryRunner类提供了两个构造方法:
(1) 默认的构造方法:
QueryRunner()
(2) 须要一个 javax.sql.DataSource 来做参数的构造方法。
QueryRunner(DataSource ds)
八、QueryRunner类的主要方法
(1) public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:执行一个查询操做,在这个查询中,对象数组中的每一个元素值被用来做为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的建立和关闭。
(2) public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException: 几乎与第一种方法同样;惟一的不一样在于它不将数据库链接提供给方法,而且它是从提供给构造方法的数据源(DataSource) 或使用的setDataSource 方法中从新得到 Connection。
(3) public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException : 执行一个不须要置换参数的查询操做。
(4) public int update(Connection conn, String sql, Object[] params) throws SQLException:用来执行一个更新(插入、更新或删除)操做。
(5) public int update(Connection conn, String sql) throws SQLException:用来执行一个不须要置换参数的更新操做。
Demo样例:使用dbutils完成数据库的crud
public class Demo1 {
/*
create database day17;
use day17;
create table users(
id int primary key,
name varchar(40),
password varchar(40),
email varchar(60),
birthday date
);
*/
public void insert() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";
Object params[] = {2,"bbb","123","aa@sina.com",new Date()};
runner.update(sql, params);
}
public void update() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "update users set email=? where id=?";
Object params[] = {"aaaaaa@sina.com",1};
runner.update(sql, params);
}
public void delete() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "delete from users where id=?";
runner.update(sql, 1);
}
@Test
public void find() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from users where id=?";
User user = (User) runner.query(sql, 1, new BeanHandler(User.class));
System.out.println(user.getEmail());
}
@Test
public void getAll() throws Exception{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from users";
List list = (List) runner.query(sql, new BeanListHandler(User.class));
System.out.println(list);
}
@Test
public void batch() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";
Object params[][] = new Object[3][5];
for(int i=0;i<params.length;i++){ //3
params[i] = new Object[]{i+1,"aa"+i,"123",i + "@sina.com",new Date()};
}
runner.batch(sql, params);
}
}
九、ResultSetHandler接口 介绍
该接口用于处理 java.sql.ResultSet,将数据按要求转换为另外一种形式。
ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
十、ResultSetHandler 接口的实现类
(1) ArrayHandler( ):把结果集中的第一行数据转成对象数组。
(2) ArrayListHandler( ):把结果集中的每一行数据都转成一个数组,再存放到List中。
(3) BeanHandler(Class type) :将结果集中的第一行数据封装到一个对应的JavaBean实例中。
(4) BeanListHandler(Class type) :将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
(5) ColumnListHandler(int columnIndex / String columnName):将结果集中某一列的数据存放到List中。
(6) KeyedHandler( int columnIndex / String columnName ):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,并将其columnName的值做为指定的key。
(7) MapHandler( ):将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
(8) MapListHandler( ):将结果集中的每一行数据都封装到一个Map里,而后再存放到List
(9) ScalarHandler( ):将结果集中的某一列 装入到一个对象中。
Demo样例:测试dbutils的各个结果集处理器
public class Demo2 {
@Test
public void test1() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from users where id=?";
Object result[] = (Object[]) runner.query(sql,1, new ArrayHandler());
System.out.println(result[0]);
System.out.println(result[1]);
}
@Test
public void test2() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from users";
List list = (List) runner.query(sql, new ArrayListHandler());
System.out.println(list);
}
@Test
public void test3() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from users";
List list = (List) runner.query(sql, new ColumnListHandler1("name"));
System.out.println(list);
}
@Test
public void test4() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from users";
Map<Integer,Map<String,Object>> map = (Map) runner.query(sql, new KeyedHandler("id"));
for(Map.Entry<Integer,Map<String,Object>> me : map.entrySet()){
int id = me.getKey();
for(Map.Entry<String, Object> entry : me.getValue().entrySet()){
String name = entry.getKey();
Object value = entry.getValue();
System.out.println(name + "=" + value);
}
}
}
@Test //获取总记录数。
public void test5() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select count(*) from users";
/* 方式一:
Object result[] = (Object[]) runner.query(sql, new ArrayHandler());
long totalrecord = (Long)result[0];
int num = (int)totalrecord;
System.out.println(num);
int totalrecord = ((Long)result[0]).intValue();
*/
//方式二:
int totalrecord = ((Long)runner.query(sql, new ScalarHandler(1))).intValue();
System.out.println(totalrecord);
}
}
//自定义
class ColumnListHandler1 implements ResultSetHandler{
private String columnName;
public ColumnListHandler1(String columnName){
this.columnName = columnName;
}
public Object handle(ResultSet rs) throws SQLException {
List list = new ArrayList();
while(rs.next()){
list.add(rs.getObject(columnName));
}
return list;
}
}
十一、JDBC应用的事务管理(ThreadLocal类)
JDBC 应用的事务管理——Service层和Dao层事务的传递。
方式一:跨层传递方法参数——在Service层建立开启事务的链接,并传递到Dao层,最后在Service层提交事务;
方式二:ThreadLocal 绑定链接——使用ThreadLocal进行事务管理——ThreadLocal能够实如今线程范围内实现数据共享。
方式三:使用Spring进行事务管理;(在Spring 博文中讲解。)
十二、JDBC应用的事务管理——采用跨层跨层传递方法参数
思想:在Service层建立开启事务的链接,并传递到Dao层,最后在Service层提交事务;
Demo样例1:Service层(Dao层中只要在方法中参数中接收该 链接参数 就行了)
public class BusinessService {
/*
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
*/
public void transfer1(int sourceid,int targetid,double money) throws SQLException{
Connection conn = null;
try{
// 获取链接并开启事务。
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false);
// 将开启事务的链接传递到各层。
AccountDao dao = new AccountDao(conn);
Account a = dao.find(sourceid); //select
Account b = dao.find(targetid); //select
a.setMoney(a.getMoney()-money);
b.setMoney(b.getMoney()+money);
dao.update(a); //update
dao.update(b);//update
// 提交事务。
conn.commit();
}finally{
// 关闭链接。
if(conn!=null) conn.close();
}
}
}
1三、JDBC应用的事务管理—— ThreadLocal 绑定链接
思想:在Service层将开启事务的链接绑定到ThreadLocal中,在当前线程所途径的其余各层从ThreadLocal中获取链接并进行操做,最后线程返回至Service层时,再提交事务,移除绑定的连接。
Demo样例1:将 使用ThreadLocal 绑定链接 的代码封装成工具类。
public class JdbcUtils {
private static DataSource ds;
// 为保证各层的类所使用的ThreadLocal是同一个,建议将其设定成静态的,可是必定要记得使用后要移出绑定在上面的对象。
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); // 其实就是一个Map集合
static{
try{
Properties prop = new Properties();
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
ds = factory.createDataSource(prop);
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static DataSource getDataSource(){
return ds;
}
// 备注:该获取链接的方法,仅当使用ThreadLocal来管理事务链接的状况,由于向静态对象ThreadLocal中绑定了对象,因此当咱们不须要管理事务的普通获取链接的方法,就不要用此方法。应该用普通的获取链接的方法。
public static Connection getConnection() throws SQLException{
try{
//获得当前线程上绑定的链接
Connection conn = tl.get();
if(conn==null){ //表明线程上没有绑定链接
conn = ds.getConnection();
tl.set(conn);
}
return conn;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void startTransaction(){
try{
//获得当前线程上绑定链接开启事务
Connection conn = tl.get();
if(conn==null){ //表明线程上没有绑定链接
conn = ds.getConnection();
tl.set(conn);
}
conn.setAutoCommit(false);
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void commitTransaction(){
try{
Connection conn = tl.get();
if(conn!=null){
conn.commit();
}
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void closeConnection(){
try{
Connection conn = tl.get();
if(conn!=null){
conn.close();
}
}catch (Exception e) {
throw new RuntimeException(e);
}finally{
tl.remove(); //千万注意,解除当前线程上绑定的连接(从threadlocal容器中移除对应当前线程的连接)
}
}
}
Demo样例2: 采用 ThreadLocal 绑定链接 来管理事务的 Service层的代码。
public class BusinessService {
/*
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
*/
//用上ThreadLocal的事务管理
public void transfer2(int sourceid,int targetid,double money) throws SQLException{
try{
JdbcUtils.startTransaction();
AccountDao dao = new AccountDao();
Account a = dao.find(sourceid); //select
Account b = dao.find(targetid); //select
a.setMoney(a.getMoney()-money);
b.setMoney(b.getMoney()+money);
dao.update(a); //update
dao.update(b);//update
JdbcUtils.commitTransaction();
}finally{
JdbcUtils.closeConnection();
}
}
}
1四、使用JDBC操做多个表
(1) 使用JDBC操做多表的步骤
(a) 明确对象的属性,及之间的关联关系。
(b) 明确表关系, 建立数据库及表;
(c) 编码Dao层的代码(重点是增删改查时涉及到的级联操做。)
(d) 编码Service层的代码(重点是 复杂对象 的级联操做。)
(2) O-R Mapping 映射的注意事项
(a) 无论java的对象存在何种关系,反映到关系型数据库中,都是使用外键表示纪录(即对象)的关联关系。
(b) 设计java对象如涉及到多个对象相互引用,要尽可能避免使用一对多,或多对多关系,而应使用多对一描述对象之间的关系(或使用延迟加载的方式)。以免查询出了全部“一对多”中 “多”的数据,容易形成内存溢出
(c) 特殊状况下(好比订单--订单项)必须设计成“一对多”关系时,当“多”的一方数据较少时,可使用级联查询,但如果“多”的一方数据量较大时,则建议使用 “分页方式”查询。
(3) “一对多”多表关联关系的设计方法:
(a) 先将每张表各自的基本属性信息列好;
(b) 再将“一对多” 多的一方中设定外键列(并添加外键约束,以维护两表之间的关系)。
(4) 经常使用O-R Mapping映射工具
(a) Hibernate
(b) Ibatis
(c) Commons DbUtils(只是对JDBC简单封装)
1五、使用JDBC操做多个表—— 一对多关系 (例如:部门和员工)
Demo样例1:Dao层的代码
public class DepartmentDao {
/*
多表设计原则
一、现将各表各自的基本属性信息列好;
二、再将“一对多” 多的一方中设定外键列(并添加外键约束,以维护两表之间的关系)。
create table department
(
id varchar(40) primary key,
name varchar(40)
);
create table employee
(
id varchar(40) primary key,
name varchar(40),
salary double,
department_id varchar(40),
constraint department_id_FK foreign key(department_id) references department(id)
);
alter table employee drop foreign key department_id_FK;
alter table employee add constraint department_id_FK foreign key(department_id) references department(id) on delete set null;
alter table employee drop foreign key department_id_FK;
alter table employee add constraint department_id_FK foreign key(department_id) references department(id) on delete cascade;
*/
public void add(Department d) throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
//1.把department对象的数据插入到department表
String sql = "insert into department(id,name) values(?,?)";
Object params[] = {d.getId(),d.getName()};
runner.update(sql, params);
//2.把department对象中维护的全部员工插入到员工表
Set<Employee> set = d.getEmployees();
for(Employee e : set){
sql = "insert into employee(id,name,salary,department_id) values(?,?,?,?)";
params = new Object[]{e.getId(),e.getName(),e.getSalary(),d.getId()};
runner.update(sql, params);
}
//3.更新员工表的外键列,说明员工的部门(本例中的ID能够实现给定,固就不须要进行更新外键列操做;但如果涉及到获取 自动生成主键 的案例时,则须要 涉及到更新外键操做)。
}
//该方法查询出了全部“一对多”中 “多”的数据,容易形成内存溢出。当“多”的一方数据较少时,可使用该级联查询,但如果“多”的一方数据量较大时,则建议使用 “分页方式”查询。
public Department find(String id) throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
//1.找部门表,查出部门的基本信息
String sql = "select * from department where id=?";
Department d = (Department) runner.query(sql, id, new BeanHandler(Department.class));
//2.找员工表,找出部门下面全部员工
sql = "select * from employee where department_id=?";
List list = (List) runner.query(sql, id, new BeanListHandler(Employee.class));
d.getEmployees().addAll(list); // 注:set集合的addAll() 是将全部的值逐个取出来,再逐一存入到Set集合中;而set集合的add()方法则是替换一Set集合的引用。
return d;
}
//111
public void delete(String id) throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql= "delete from department where id=?";
runner.update(sql, id);
}
}
Demo样例2:Service层的代码
public class BService {
@Test
public void add() throws SQLException{
Department d = new Department();
d.setId("111");
d.setName("开发部");
Employee e1 = new Employee();
e1.setId("1");
e1.setName("aa");
e1.setSalary(10000);
Employee e2 = new Employee();
e2.setId("2");
e2.setName("bb");
e2.setSalary(10000);
d.getEmployees().add(e1);
d.getEmployees().add(e2);
DepartmentDao dao = new DepartmentDao();
dao.add(d);
}
@Test
public void find() throws SQLException{
DepartmentDao dao = new DepartmentDao();
Department d = dao.find("111");
System.out.println(d);
}
@Test
public void delete() throws SQLException{
DepartmentDao dao = new DepartmentDao();
dao.delete("111");
}
}
1六、使用JDBC操做多个表—— 多对多关系 (老师和学生)
Demo样例1:Dao层的代码
public class TeacherDao {
/*
create table teacher
(
id varchar(40) primary key,
name varchar(40),
salary double
) ;
create table student
(
id varchar(40) primary key,
name varchar(40)
);
create table teacher_student
(
teacher_id varchar(40),
student_id varchar(40),
primary key(teacher_id,student_id),
constraint teacher_id_FK foreign key(teacher_id) references teacher(id),
constraint student_id_FK foreign key(student_id) references student(id)
);
alter table teacher_student drop foreign key teacher_id_FK;
alter table teacher_student add constraint teacher_id_FK foreign key(teacher_id) references teacher(id) on delete cascade;
alter table teacher_student drop foreign key student_id_FK;
alter table teacher_student add constraint student_id_FK foreign key(student_id) references student(id) on delete cascade;
*/
public void add(Teacher t) throws SQLException {
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
//1`.取出老师存老师表
String sql = "insert into teacher(id,name,salary) values(?,?,?)";
Object params[] = {t.getId(),t.getName(),t.getSalary()};
runner.update(sql, params);
//2.取出老师全部学生的数据,存学生表
Set<Student> set = t.getStudents();
for(Student s : set){
sql = "insert into student(id,name) values(?,?)";
params = new Object[]{s.getId(),s.getName()};
runner.update(sql, params);
//3.更新中间表,说明老师和学生的关系
sql = "insert into teacher_student(teacher_id,student_id) values(?,?)";
params = new Object[]{t.getId(),s.getId()};
runner.update(sql, params);
}
}
public Teacher find(String id) throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
//1.找老师表,找出老师的基本信息
String sql = "select * from teacher where id=?";
Teacher t = (Teacher) runner.query(sql, id, new BeanHandler(Teacher.class));
//2.找出老师的全部学生 ()
//sql = "select s.* from teacher_student ts,student s where ts.teacher_id=? and ts.student_id=s.id";
sql = "select s.* from teacher_student ts,student s where ts.teacher_id=? and ts.student_id=s.id";
List list = (List) runner.query(sql, id, new BeanListHandler(Student.class));
t.getStudents().addAll(list);
return t;
}
public void delete(String id){
QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
String sql = "delete from teacher where id=?";
}
}
Demo样例2:Service层的代码
public class BService {
@Test
public void addTeacher() throws SQLException{
Teacher t = new Teacher();
t.setId("1");
t.setName("老张");
t.setSalary(100000);
Student s1 = new Student();
s1.setId("1");
s1.setName("aa");
Student s2 = new Student();
s2.setId("2");
s2.setName("bb");
t.getStudents().add(s1);
t.getStudents().add(s2);
TeacherDao dao = new TeacherDao();
dao.add(t);
}
@Test
public void findTeacher() throws SQLException{
TeacherDao dao = new TeacherDao();
Teacher t = dao.find("1");
System.out.println(t);
}
}
1七、数据库端——表关系间的级联操做
表关系间的级联操做:
REFERENCES tbl_name [(index_col_name,...)]
[MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
[ON DELETE reference_option] (级联删除)
[ON UPDATE reference_option] (级联修改)
reference_option的可选值:
RESTRICT | CASCADE(删除) | SET NULL(置空) | NO ACTION
Demo:给表添加外键约束——包含级联删除(置空)的关系
alter table employee add constraint department_id_FK foreign key(department_id) references department(id) on delete set null ;
alter table employee add constraint department_id_FK foreign key(department_id) references department(id) on delete set null;
alter table employee add constraint department_id_FK foreign key(department_id) references department(id) on delete cascade;
敬请评论(1)若您以为本文 有用处 —— 请留言评论,以坚决其余 IT童鞋 阅读本文的信心。(2)若您以为本文 没用处 —— 请留言评论,笔者将会改进不足,以便为你们整理更加好用的笔记。