您的位置:首页 > 运维架构 > 网站架构

JDBC简单操作(三层架构以及简单工厂的实现)

2016-10-11 19:04 363 查看
写一个初始实现类

package niit.jdbc.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JdbcUtil {
static String URL = "jdbc:mysql://localhost:3306/niit?characterEncoding=utf8";
static String USER = "root";
static String PASSWORD = "root";

static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
public static Connection getConnection(){
Connection con = threadLocal.get();
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(threadLocal.get()==null){
con = DriverManager.getConnection(URL,USER,PASSWORD);
threadLocal.set(con);
}

} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return con;

}
public static TransactionManager getTransactionManager(){
return new TransactionManager(getConnection());
}

public static void free(Connection con){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
threadLocal.remove();
}
}
}
里面有一个getTransactionManager的方法,是用于事务的操作。主要用于回滚。这个我后面解释一下

写一个工具类,用于数据库的增删改查功能

package niit.jdbc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import niit.jdbc.util.JdbcUtil;

public  class BaseDao <T>{

public void upDate(String sql,List<Object> list){
Connection con = null;
PreparedStatement pre = null;
con = JdbcUtil.getConnection();
try {
pre = con.prepareStatement(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int temp = 1;

for (Object object : list) {
try {
pre.setObject(temp, object);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

temp++;
}
try {
pre.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
if(con.getAutoCommit()){
JdbcUtil.free(con);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
public List<T> select(String sql,List<Object> selectList,MapRower<T>mr){
Connection con = null;
PreparedStatement pre = null;
ResultSet rs = null;

List<T> list = new ArrayList<>();
con = JdbcUtil.getConnection();
try {
pre = con.prepareStatement(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int temp = 1;

for (Object object : selectList) {
try {
pre.setObject(temp, object);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

temp++;
}

try {
rs = pre.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(rs != null){
list =  mr.maprower(rs);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JdbcUtil.free(con);
}
return list;
}

}

我们用一个创建一个Student表,分别包含属性,学号,姓名,年龄以及地址。并创建Student的类用于Beans,我就不写了

还有就是在Update方法中关闭连接的时候我做了一下判断,主要是用于事务的实现。因为假如有两个表,两个表有外键连接,我们去删除一个表中的外键字段,就要先去另外一个表中删掉使用这个字段的所有字段。如果发生了断电或者异常只是执行了一半,我们必须实现回滚的操作。所以要用到事务。先看一下表

import java.sql.Connection;
import java.sql.SQLException;

public class TransactionManager {
private Connection con;

public TransactionManager(Connection con) {
super();
this.con = con;
}
//关闭自动提交
public void statrOfCommit(){
try {
con.setAutoCommit(false);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//提交
public void CommintAndFree(){
try {
con.commit();
JdbcUtil.free(con);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//回流
public void RollbackAndFree(){
try {
con.rollback
4000
();
JdbcUtil.free(con);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}因为我们要进行回滚就要先关闭系统的自动提交,所以用这个方法去判断我们执行的操作是否有可能需要回滚,如果不需要,就可以关闭方法
还有一个就是因为我想保证在一个线程中只用一个连接,这样的话,可以加大问的便捷性

在上上段代码中,用了MapRower<T>mr   这是一个接口,用这个接口的主要目的就是因为得到ResultSet后不能直接使用Student类别转换,所以在MapRower中的maprower传入ResultSet并得到List   这样可以更加灵活是用数据库的查询语句。

我使用maprower是使用匿名内部类实现,如下:package niit.jdbc.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import niit.jdbc.dao.BaseDao;
import niit.jdbc.po.StudentPO;
import niit.jdbc.vo.Student;
import niit.jdbc.dao.MapRower;
import niit.jdbc.dao.StudentDao;

public class StudentDaoImpl extends BaseDao<Student> implements StudentDao{

public void getInsert(Student stu){
String sql = "insert into student values (?,?,?,?)";
List<Object> list = new ArrayList<>();
list.add(stu.getSno());
list.add(stu.getSname());
list.add(stu.getAddress());
list.add(stu.getAge());
this.upDate(sql, list);
}
public void getSelect(int sno){
String sql = "delete from student where sno = ?";
List<Object> list = new ArrayList<>();
list.add(sno);
this.upDate(sql, list);
}
/*
* 没改呢
*/
public void getUpdate(Student stu){
String sql = "insert into student values (?,?,?,?)";
List<Object> list = new ArrayList<>();
list.add(stu.getSno());
list.add(stu.getSname());
list.add(stu.getAddress());
list.add(stu.getAge());
this.upDate(sql, list);
}

public List<Student> getSelect(StudentPO stupo){

String sql = "select * from student where 1=1";
List<Object> getStu = new ArrayList<>();
if(stupo.getName()!=null){
sql = sql + " and sname = ?";
getStu.add(stupo.getName());
}
if(stupo.getAgeFrom()!= null){
sql = sql + " and age > ?";
getStu.add(stupo.getAgeFrom());
}
if(stupo.getAgeTo()!= null){
sql = sql + " and age < ?";
getStu.add(stupo.getAgeTo());
}
return this.select(sql, getStu,new MapRower<Student>(){

@Override
public List<Student> maprower(ResultSet rs) {
List<Student> list = new ArrayList<>();
Student stu = null;
try {
while(rs.next()){
stu = new Student();
stu.setSno(rs.getInt("sno"));
stu.setSname(rs.getString("sname"));
stu.setAddress(rs.getString("address"));
stu.setAge(rs.getInt("age"));
list.add(stu);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}

});

}其中Update因为没有想好查询语句和修改值就没有写,其实比较懒而已。上面就是Student在Dao层的实现,因为避免耦合,都是使用接口实现,这里没有就不上传接口代码,接口的名字就是实现类的名字去掉impl。
可能观察到了,我在Select方法中传入的是StudentPO,StudentPO的属性包扣,姓名和年龄的区间(两个Integer,使用Integer的原因是int的NULL值的默认值是0,不方便判断),所在在查询语句可以根据姓名、年龄区间查询。

下面是Serivce层。代码如下:package niit.jdbc.service.impl;

import java.util.List;

import niit.jdbc.dao.StudentDao;
import niit.jdbc.po.StudentPO;
import niit.jdbc.production.impl.GetStudentDaoProduction;
import niit.jdbc.service.StudentService;
import niit.jdbc.vo.Student;

public class StudentServiceImpl implements StudentService{
private StudentDao studentdao= GetStudentDaoProduction.getS();
@Override
public void serviceInsert(Student stu) {
// TODO Auto-generated method stub
studentdao.getInsert(stu);
}

@Override
public void serviceSelect(int sno) {
// TODO Auto-generated method stub
studentdao.getSelect(sno);
}

@Override
public void serviceUpdate(Student stu) {
// TODO Auto-generated method stub
studentdao.getUpdate(stu);
}

@Override
public List<Student> serviceSelect(StudentPO stupo) {
// TODO Auto-generated method stub
return studentdao.getSelect(stupo);
}

}
其中我获取StudentDao的时候是使用简单工厂模式,这里的主要作用是用于解耦
下面是工厂接口的实现类import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import niit.jdbc.dao.StudentDao;
import niit.jdbc.production.StudentDaoproduction;

public class StudentDaoproductionImpl implements StudentDaoproduction {

@Override
public StudentDao getStudenDao() {
// TODO Auto-generated method stub
Class clazz = null;
try {
clazz = Class.forName("niit.jdbc.dao.impl.StudentDaoImpl");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Constructor ctor = null;
try {
ctor = clazz.getConstructor();
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Object obj = null;
try {
obj = ctor.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (StudentDao) obj;
}

}
下面是工厂的实现:
import niit.jdbc.dao.StudentDao;
import niit.jdbc.production.StudentDaoproduction;

public class GetStudentDaoProduction {
public static StudentDao getS() {
StudentDaoproduction sd = null;
try {
sd = (StudentDaoproduction) Class.forName("niit.jdbc.production.impl.StudentDaoproductionImpl")
.newInstance();

} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// Class.forname("niit.jdbc.production.impl.StudentDaoproductionImpl")
// StudentDaoproductionImpl.class
return sd.getStudenDao();
}
}
下面就是测试类。(没有写UI,很尴尬)
package niit.jdbc.test;

import niit.jdbc.service.StudentService;
import niit.jdbc.service.impl.StudentServiceImpl;
import niit.jdbc.vo.Student;

public class Test01 {
public static void main(String[] args) {
StudentService ss = new StudentServiceImpl();
Student stu = new Student();
stu.setSno(1004);
stu.setSname("张四");
stu.setAddress("中关村");
stu.setAge(50);
ss.serviceInsert(stu);
}
}
这个测试类就是添加语句,没有什么可说的。很简单
import niit.jdbc.service.StudentService;
import niit.jdbc.service.impl.StudentServiceImpl;
import niit.jdbc.util.JdbcUtil;
import niit.jdbc.util.TransactionManager;
import niit.jdbc.vo.Student;

public class Test02 {
public static void main(String[] args) {
StudentService studentSetivce = new StudentServiceImpl();
Student stu = new Student();
stu.setSno(1005);
stu.setSname("张四");
stu.setAddress("中关村");
stu.setAge(50);
Student stu1 = new Student();
stu1.setSno(1006);
stu1.setSname("张四");
stu1.setAddress("中关村");
stu1.setAge(50);
TransactionManager tm = JdbcUtil.getTransactionManager();
tm.statrOfCommit();
try{
studentSetivce.serviceInsert(stu);
int i =5/0;
System.out.println(i);
studentSetivce.serviceInsert(stu1);
tm.CommintAndFree();
}catch(Exception e){
e.printStackTrace();
tm.RollbackAndFree();
}
}
}
这个测试类就是利用了一下事务的回滚操纵,在两个添加语句中故意写了一个异常。当catch到异常的时候进行回滚操作并关闭连接。如果没有catch到异常,就执行操作并关闭连接

OK,就是这样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐