JDBC操作封装
文件结构如下:
代码如下:
//对应数据库的user表格,这个类的成员名必须和数据库的属性名相同,或者和sql语句的别名相同。
import java.util.Date;
public class User {
private int id;
private String username;
private Date birthday;
//sql.Date是util.Date的子类,这里直接运用多态来接收。
private String sex;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address=" + address
+ "]";
}
public User(int id, String username, Date birthday, String sex, String address) {
super();
this.id = id;
this.username = username;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}
public User() {
super();
}
}
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
//获得connection数据库连接的工具类,可以创建和关闭JDBC相关对象。
public class JDBCUtils {
public static Connection getConnection() throws Exception {
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//采用读取配置文件的方式去创建,增加的程序的灵活性,拓展性。
Properties pros = new Properties();
pros.load(is);
String url = pros.getProperty("url");
String user = pros.getProperty("user");
String password = pros.getProperty("password");
Class.forName(pros.getProperty("driverClass"));
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
public static void closeResource(Connection conn,PreparedStatement ps,ResultSet rs) {
try {
if(conn!=null) conn.close();
if(ps!=null) ps.close();
if(rs!=null) rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.test.JDBCutils.JDBCUtils;
//BaseDao类,增删改查操作的基本类,统一封装了增删改查的基本操作。
public class BaseDao {
public int update(Connection conn,String sql,Object...args) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for(int i=0;i<args.length;i++) {
ps.setObject(i+1, args[i]);
}
return ps.executeUpdate();
//返回的是更新的行数
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(null, ps,null);
}
return 0;
}
//运行泛类,增强拓展性
public <T> T getInstance(Connection conn,Class<T> clazz,String sql,Object...args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for(int i=0;i<args.length;i++) {
ps.setObject(i+1, args[i]);
}
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
//获取元数据
int count = rsmd.getColumnCount();
//获取表格列数
if(rs.next()) {
T t = clazz.newInstance();
//通过反射创建对象
for(int i=0;i<count;i++) {
Object value = rs.getObject(i+1);
String column = rsmd.getColumnLabel(i+1);
//获取指定列数的,列名。
Field field = clazz.getDeclaredField(column);
field.setAccessible(true);
field.set(t, value);
//通过反射修改对象的private属性。
}
return t;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(null, ps,rs);
}
return null;
}
public <T> List<T> getForList(Connection conn,Class<T> clazz,String sql,Object...args) {
PreparedStatement ps = null;
ResultSet rs = null;
List<T> list = new ArrayList<>();
try {
ps = conn.prepareStatement(sql);
for(int i=0;i<args.length;i++) {
ps.setObject(i+1, args[i]);
}
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
while(rs.next()) {
T t = clazz.newInstance();
for(int i=0;i<count;i++) {
Object value = rs.getObject(i+1);
String column = rsmd.getColumnLabel(i+1);
Field field = clazz.getDeclaredField(column);
field.setAccessible(true);
field.set(t, value);
}
list.add(t);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(null, ps,rs);
}
return list;
}
//针对特殊语言查询的方法,返回值根据语句不同而不同
public <T> T getValue(Connection conn,String sql,Object...args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for(int i=0;i<args.length;i++) {
ps.setObject(i+1, args[i]);
}
rs = ps.executeQuery();
if(rs.next()) {
return (T)rs.getObject(1);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}finally {
JDBCUtils.closeResource(null, ps,rs);
}
return null;
}
}
import java.sql.Connection;
import java.util.List;
import com.test.transaction.User;
//定义接口类,来规范实现类的操作,不同表有不同的接口类,和不同的实现类
public interface UserDao {
void insert(Connection conn,User user);
void deletById(Connection conn,int id);
void updateById(Connection conn,User user);
User getById(Connection conn,int id);
List<User> getAll(Connection conn);
Long getCount(Connection conn);
}
import java.sql.Connection;
import java.util.List;
import com.test.transaction.User;
//定义实现类继承BaseDao基础类,实现不同表的接口
public class UserDaoImp extends BaseDao implements UserDao{
@Override
public void insert(Connection conn, User user) {
String sql = "insert into user(id,username,birthday,sex,address) values(?,?,?,?,?)";
update(conn,sql,0,user.getUsername(),user.getBirthday(),user.getSex(),user.getAddress());
}
@Override
public void deletById(Connection conn, int id) {
String sql = "delete from user where id = ?";
update(conn,sql,id);
}
@Override
public void updateById(Connection conn, User user) {
String sql = "update user set username=?,birthday=?,sex=?,address=? where id=?";
update(conn,sql,user.getUsername(),user.getBirthday(),user.getSex(),user.getAddress(),user.getId());
}
@Override
public User getById(Connection conn, int id) {
String sql = "select * from user where id=?";
return getInstance(conn,User.class,sql,id);
}
@Override
public List<User> getAll(Connection conn) {
String sql = "select * from user";
return getForList(conn,User.class,sql);
}
@Override
public Long getCount(Connection conn) {
String sql = "select count(*) from user";
return getValue(conn,sql);
}
}
import static org.junit.jupiter.api.Assertions.fail;
import java.sql.Connection;
import java.util.Date;
import java.util.List;
import org.junit.jupiter.api.Test;
import com.test.JDBCutils.JDBCUtils;
import com.test.dao.UserDaoImp;
import com.test.transaction.User;
//测试类创建步骤,创建Junit测试类,指定要测试的类,每个方法单独测试。
class UserDAOImpTest {
UserDaoImp imp = new UserDaoImp();
@Test
void testInsert() {
Connection conn;
try {
conn = JDBCUtils.getConnection();
User user = new User(1,"亚索",new Date(99892793L),"男","爱哦尼亚");
imp.insert(conn, user);
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
void testDeletById() {
Connection conn;
try {
conn = JDBCUtils.getConnection();
imp.deletById(conn, 8);
conn.close();
System.out.println("修改成功");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
void testUpdateById() {
fail("Not yet implemented");
}
@Test
void testGetById() {
fail("Not yet implemented");
}
@Test
void testGetAll() {
Connection conn;
try {
conn = JDBCUtils.getConnection();
List<User> list = imp.getAll(conn);
conn.close();
for(User u:list) {
System.out.println(u);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
void testGetCount() {
Connection conn;
try {
conn = JDBCUtils.getConnection();
System.out.println(imp.getCount(conn));
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//jdbc.properties配置文件
user=root
password=1171460872
url=jdbc:mysql://localhost:3306/mysqltest?useUnicode=true&characterEncoding=UTF8
driverClass=com.mysql.jdbc.Driver
//注意url的?后面内容。
/*添加的作用是:指定字符的编码、解码格式。
例如:mysql数据库用的是gbk编码,而项目数据库用的是utf-8编码。这时候如果添加了useUnicode=true&characterEncoding=UTF-8 ,那么作用有如下两个方面:
1. 存数据时:
数据库在存放项目数据的时候会先用UTF-8格式将数据解码成字节码,然后再将解码后的字节码重新使用GBK编码存放到数据库中。
2.取数据时:
在从数据库中取数据的时候,数据库会先将数据库中的数据按GBK格式解码成字节码,然后再将解码后的字节码重新按UTF-8格式编码数据,最后再将数据返回给客户端。*/
部分结果展示:
学习心得:
1.了解了框架搭建的基本原理,与设计思路。如:泛类,接口,基础类,反射,配置文件等。
2.掌握了JDBC的基本应用。
3.学习使用单元测试。
4.当数据库和Java程序编码格式不同时,读写会出现乱码,解决方法就是要在配置文件的url中设置。