目录
二、体会dao模式_简单工厂模式_插入mysql数据库支持中文
step1,实体类--->entity包,Employee类
step2,dao接口--->dao包,EmployeeDAO接口
step3,实现dao接口--->dao.jdbc包,实现类
step5,封装数据库连接类--->util包,DBUtil类
step6,配置文件--->util包,dao.properties
一、前言
上一篇文章我们介绍了dao 、一个servlet处理多种请求、servlet处理请求资源路径、将中文数据插入数据库等理论知识点,详细可参见博文:原创 java服务器端开发-servlet:4、dao 、一个servlet处理多种请求、servlet处理请求资源路径、将中文数据插入数据库 这篇文章我们将来演示一个案例:体会dao形式_简单工厂模式_插入mysql数据库支持中文
二、体会dao模式_简单工厂模式_插入mysql数据库支持中文
1、理论知识点
可参见博文:
原创 java服务器端开发-servlet:4、dao 、一个servlet处理多种请求、servlet处理请求资源路径、将中文数据插入数据库
2、代码验证测试
step1,实体类--->entity包,Employee类
比如,可以设计一个Employee类,与t_emp 表对应。
package entity;
/**
* 比如,可以设计一个Employee类,与t_emp 表对应。
*/
public class Employee {
private int id;
private String name;
private double salary;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return name + " " + salary + " " + age;
}
}
step2,dao接口--->dao包,EmployeeDAO接口
在该接口当中,声明一系列方法,这些方法
不要涉及任何具体的实现技术。
比如:
EmployeeDAO接口
public ResultSet findAll(); //error
public List<Employee> findAll();
package dao;
import java.util.List;
import entity.Employee;
/**
* 在该接口当中,声明一系列方法,
* 这些方法不要涉及任何具体的实现技术。
*/
public interface EmployeeDAO {
//public void save(Employee e)throws SQLException;//error
//public ResultSet findAllD(); //error
public List<Employee> findAll() throws Exception;
public void save(Employee e) throws Exception;
}
step3,实现dao接口--->dao.jdbc包,实现类
比如: 可以有多个类实现implements接口
这里EmployeeDAOImpl类,使用jdbc技术来实现数据库访问。
package dao.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import util.DBUtil;
import dao.EmployeeDAO;
import entity.Employee;
/**
* 可以有多个类实现implements接口
* 这里EmployeeDAOImpl类,使用jdbc技术来实现数据库访问
*/
public class EmployeeDAOImpl implements EmployeeDAO{
/**
* 查询所有员工信息
*/
public List<Employee> findAll() throws Exception {
//JPA是Java Persistence API的简称,中文名Java持久层API,
//是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
//https://baike.baidu.com/item/JPA/5660672?fr=aladdin
System.out.println("使用jpa技术实现的查找方法...");
List<Employee> employees =
new ArrayList<Employee>();
Connection conn = null;
PreparedStatement prep = null;
ResultSet rst = null;
try{
conn = DBUtil.getConnection();
prep = conn.prepareStatement(
"select * from t_emp");
rst = prep.executeQuery();
while(rst.next()){
Employee e = new Employee();
e.setId(rst.getInt("id"));
e.setName(rst.getString("name"));
e.setSalary(rst.getDouble("salary"));
e.setAge(rst.getInt("age"));
employees.add(e);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(rst != null){
rst.close();
}
if(prep != null){
prep.close();
}
DBUtil.close(conn);
}
return employees;
}
/**
* 添加新员工信息
*/
public void save(Employee e) throws Exception {
Connection conn = null;
PreparedStatement prep = null;
try{
conn = DBUtil.getConnection();
prep =
conn.prepareStatement("insert into " +
"t_emp(name,salary,age) " +
"values(?,?,?)");
prep.setString(1, e.getName());
prep.setDouble(2, e.getSalary());
prep.setInt(3, e.getAge());
prep.executeUpdate();
}catch(Exception e1){
e1.printStackTrace();
throw e1;
}finally{
if( prep != null){
prep.close();
}
DBUtil.close(conn);
}
}
}
step4,工厂--->util包,Factory类
"工厂"是一种设计模式,工厂为调用者提供,符合接口要求的对象(即产品)。
package util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 工厂类
* 工厂"是一种设计模式,工厂为调用者提供,符合接口要求的对象(即产品)。
*
* 依据type(接口名称)返回一个符合该接口要求的对象。
* 可以将type与实现类的对应关系写在配置文件(dao.properties)里面。
* Factory读该配置文件,依据配置文件的内容来创建合适的对象。
*/
public class Factory {
private static Properties props = new Properties();
static{
InputStream ips = null;
/*
* ClassLoader:类加载器(JVM调用类加载器来
* 完成类的加载:即类加载器要查找类的字节
* 码文件,并且将字节码文件的内容读入到方法
* 区,转换成一个class对象。
*/
//getClassLoader返回该类的类加载器。
ClassLoader loader =
Factory.class.getClassLoader();
//getResourceAsStream返回读取指定资源的输入流。
ips = loader.getResourceAsStream(
"util/dao.properties");
try {
//load从输入流中读取属性列表(键和元素对)。
props.load(ips);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getValue(String key){
//依据"key"找到类名
return props.getProperty(key);
}
/**
* 创建某个对象的实例
* "工厂"是一种设计模式,工厂为调用者提供
* 符合接口要求的对象(即产品)。
* @param type
* @return
* @throws Exception
*/
public static Object getInstance(String type)
throws Exception{
Object obj = null;
//依据"key"找到类名
String className = getValue(type);
System.out.println("className--->"+className);
//【包类名】,如:dao.jdbc.ClassXXX
try {
//依据类名,通过反射机制创建一个实例
Class c = Class.forName(className);
//通过class对象创建一个实例。
obj = c.newInstance();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return obj;
}
}
step5,封装数据库连接类--->util包,DBUtil类
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* jdbc 连接管理工具类
*/
public class DBUtil {
public static Connection getConnection()
throws Exception{
Connection conn = null;
try {
//Class.forName("com.mysql.jdbc.Driver"); //提示被弃用
Class.forName("com.mysql.cj.jdbc.Driver");
// conn = DriverManager.getConnection(
// "jdbc:mysql://localhost:3306/jsd1108db",
// "root","你mysql密码");
//设置,插入mysql数据库支持中文:
//"?useUnicode=true&characterEncoding=utf8",
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/jsd1108db"+
"?useUnicode=true&characterEncoding=utf8",
"root","你的mysql密码");
}catch(Exception e){
e.printStackTrace();
throw e;
}
return conn;
}
public static void close(Connection conn){
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
System.out.println(getConnection());
}
}
step6,配置文件--->util包,dao.properties
#配置文件(key=value形式)
#PackageClass = dao.jdbc.ClassXXX
EmployeeDAO=dao.jdbc.EmployeeDAOImpl
step7,测试--->test包,TestCode类
package test;
import org.junit.Test;
import dao.EmployeeDAO;
import entity.Employee;
import util.Factory;
public class TestCode {
public static void main(String[] args) throws Exception {
TestCode testCode = new TestCode();
testCode.testSave();
testCode.testFindAll();
}
@Test
public void testFindAll() throws Exception {
//工厂模式创建一个实例
EmployeeDAO dao =
(EmployeeDAO)Factory.getInstance(
"EmployeeDAO");
System.out.println("---"+dao.findAll());
}
@Test
public void testSave() throws Exception {
EmployeeDAO dao =
(EmployeeDAO)Factory.getInstance(
"EmployeeDAO");
Employee e = new Employee();
e.setName("帅气华");
e.setSalary(20000);
e.setAge(22);
dao.save(e);
}
}
3、运行程序-效果展示
(1)main方法运行测试
(2)junit 单元测试
(3)如果没有添加 JUnit4 库,报异常
如果没有添加 JUnit4 库,可能会报如下红叉异常:
可点红叉添加 JUnit4 库
或者点击Fix project setup...,进行添加 JUnit4 库
三、执行流程_简单小结
@Test
public void testFindAll() throws Exception {
//工厂模式创建一个实例
EmployeeDAO dao = (EmployeeDAO)Factory.getInstance("EmployeeDAO");
System.out.println("dao:"+dao);//dao.jdbc.EmployeeDAOImpl@32a1bec0
System.out.println("查询结果:"+dao.findAll());
}
---语句1:
工厂模式创建一个实例
EmployeeDAO dao = (EmployeeDAO)Factory.getInstance("EmployeeDAO");
---语句2:
父接口引用EmployeeDAO对象--->指向子类EmployeeDAOImpl对象
所以得到的是EmployeeDAOImpl对象
System.out.println("dao:"+dao);//dao.jdbc.EmployeeDAOImpl@32a1bec0
---语句3:
System.out.println("查询结果:"+dao.findAll());
父接口EmployeeDAO,定义了findAll方法
public List<Employee> findAll() throws Exception;
子类 EmployeeDAOImpl 实现了 findAll方法
public List<Employee> findAll() throws Exception {
。。。
}
所以这里实际上调用的是:子类EmployeeDAOImpl的 findAll方法
System.out.println("查询结果:"+dao.findAll());
返回的是 List<Employee> 对象,所以打印输出如下:
查询结果:[帅气华 20000.0 22]