Java学习笔记-Day67 Spring 框架(五)
一、Spring JDBC
1、Spring JDBC的工作模式
Spring主要提供JDBC模板方式、关系数据库对象化方式和SimpleJdbc方式三种方式来简化JDBC编程,这三种方式就是Spring JDBC的工作模式。
(1)JDBC模板方式:Spring JDBC框架提供以下模板类来简化JDBC编程,实现GoF模板设计模式,将可变部分和非可变部分分离,可变部分采用回调接口方式由用户来实现。
(2)关系数据库操作对象化方式:Spring JDBC框架提供了将关系数据库操作对象化的表示形式,从而使用户可以采用面向对象编程来完成对数据库的访问。如MappingSqlQuery、SqlUpdate、SqlCall、SqlFunction、StoredProcedure等类。这些类的实现一旦建立即可重用并且是线程安全的。
(3)SimpleJdbc方式:Spring JDBC框架还提供了SimpleJdbc方式来简化JDBC编程,SimpleJdbcInsert 、 SimpleJdbcCall用来简化数据库表插入、存储过程或函数访问。
2、SimpleJdbc方式
JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的。
JdbcTemplate类通过模板设计模式帮助消除冗长的代码,只做需要做的事情(即可变部分),并且自动完成固定部分,如连接的创建及关闭。JdbcTemplate类对可变部分采用回调接口方式实现,如ConnectionCallback通过回调接口返回给用户一个连接,从而可以使用该连接做任何事情、StatementCallback通过回调接口返回给用户一个Statement,从而可以使用该Statement做任何事情。
Spring提供了一个工具类JdbcTemple,该类对jdbc的操作进行了轻量级别的封装。
优点:
- 直接使用sql语句操作数据库,效率很高。
- 支持数据库的分区,这是数据量大的项目的实现方案,hibernate无法实现。
- 使用java语言拼sql语句,效率很高,这是ibatis无法达到的。
缺点:
- sql语句直接写在java程序中,很难管理,但可以进行二次封装,实现sql语句的简单管理。
- 编码量相对ORM解决方案还是偏大。
使用JdbcTemplate模板类时必须通过DataSource获取数据库连接,Spring JDBC提供了DriverManagerDataSource实现,它通过包装DriverManager.getConnection获取数据库连接。
二、Spring JDBC的实现案例
1、SimpleJdbc方式(基于XML配置实现)
(1) BaseDao 类(获取数据库连接)
package com.etc.aop.dao;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
public class BaseDao {
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public Connection getConn() throws SQLException {
return dataSource.getConnection();
}
}
(2)UsersDao 接口
package com.etc.aop.dao;
import com.etc.aop.entity.Users;
public interface UsersDao {
public boolean addUsers(Users user);
}
(3)UsersDao 接口的实现类
package com.etc.aop.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.etc.aop.dao.BaseDao;
import com.etc.aop.dao.UsersDao;
import com.etc.aop.entity.Users;
public class UsersDaoImpl implements UsersDao {
private BaseDao bd;
public BaseDao getBd() {
return bd;
}
public void setBd(BaseDao bd) {
this.bd = bd;
}
@Override
public boolean addUsers(Users user) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = bd.getConn();
pstmt = conn.prepareStatement("insert into users(userid,username,userpwd) values(?,?,?);");
pstmt.setInt(1, user.getUserid());
pstmt.setString(2, user.getUsername());
pstmt.setString(3, user.getUserpwd());
int result = pstmt.executeUpdate();
if (result > 0) {
return true;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return false;
}
}
(4)UsersService 接口
package com.etc.aop.service;
import com.etc.aop.entity.Users;
public interface UsersService {
public boolean addUsers(Users user);
}
(5)UsersService 接口的实现类
package com.etc.aop.service.impl;
import com.etc.aop.dao.UsersDao;
import com.etc.aop.entity.Users;
import com.etc.aop.service.UsersService;
public class UsersServiceImpl implements UsersService {
private UsersDao ud;
public UsersDao getUd() {
return ud;
}
public void setUd(UsersDao usersdao) {
this.ud = usersdao;
}
@Override
public boolean addUsers(Users user) {
return ud.addUsers(user);
}
}
(4)切面类(环绕通知,进行日志记录)
package com.etc.aop.log;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import com.etc.aop.entity.Users;
@Aspect
public class LogAop {
@Around(value="execution(* com.etc.aop.dao.impl.*.*(..))")
public Object writeLog(ProceedingJoinPoint pjp) throws Throwable {
Object obj = pjp.proceed();
boolean flag = Boolean.parseBoolean(obj.toString());
System.out.println("aop flag="+flag);
Object[] objs = pjp.getArgs();
FileWriter fw = new FileWriter("log.txt",true);
//将Date类对象格式化成字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss ");
String dateStr = sdf.format(new Date());
String username = ((Users)objs[0]).getUsername();
if(flag) {
fw.append(dateStr+"--"+username+"-- 注册成功\r\n");
}else {
fw.append(dateStr+"--"+username+"-- 注册失败\r\n");
}
fw.close();
return obj;
}
}
(5)测试类
package com.etc.aop.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.etc.aop.entity.Users;
import com.etc.aop.service.UsersService;
@SpringJUnitConfig(locations="classpath:springaop.xml")
public class TestRegister {
@Autowired
UsersService us;
@Test
public void test() {
Users user= new Users(120, "tom", "1234");
boolean flag = us.addUsers(user);
System.out.println("test flag="+flag);
}
}
(6)Spring全局配置文件:springaop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean class="com.etc.aop.log.LogAop"></bean>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="url" value="jdbc:mysql://localhost:3306/userdb?serverTimezone=Asia/Shanghai"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
</bean>
<bean class="com.etc.aop.dao.BaseDao" id="bd">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean class="com.etc.aop.dao.impl.UsersDaoImpl" id="ud">
<property name="bd" ref="bd"></property>
</bean>
<bean class="com.etc.aop.service.impl.UsersServiceImpl" id="us">
<property name="ud" ref="ud"></property>
</bean>
</beans>
2、SimpleJdbc方式(基于注解实现)
(1) BaseDao 类(获取数据库连接)
package com.etc.aop.dao;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component(value="bd")
public class BaseDao {
@Autowired
private DataSource dataSource;
public Connection getConn() throws SQLException {
return dataSource.getConnection();
}
}
(2)实体类Users
package com.etc.aop.entity;
public class Users {
private int userid;
private String username;
private String userpwd;
public Users(int userid, String username, String userpwd) {
super();
this.userid = userid;
this.username = username;
this.userpwd = userpwd;
}
public Users() {
super();
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpwd() {
return userpwd;
}
public void setUserpwd(String userpwd) {
this.userpwd = userpwd;
}
@Override
public String toString() {
return "Users [userid=" + userid + ", username=" + username + ", userpwd=" + userpwd + "]";
}
}
(3)UsersDao 接口
package com.etc.aop.dao;
import com.etc.aop.entity.Users;
public interface UsersDao {
public boolean addUsers(Users user);
}
(4)UsersDao 接口的实现类UsersDaoImpl
package com.etc.aop.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.etc.aop.dao.BaseDao;
import com.etc.aop.dao.UsersDao;
import com.etc.aop.entity.Users;
@Repository(value="ud")
public class UsersDaoImpl implements UsersDao {
@Autowired
private BaseDao bd;
@Override
public boolean addUsers(Users user) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = bd.getConn();
pstmt = conn.prepareStatement("insert into users(userid,username,userpwd) values(?,?,?);");
pstmt.setInt(1, user.getUserid());
pstmt.setString(2, user.getUsername());
pstmt.setString(3, user.getUserpwd());
int result = pstmt.executeUpdate();
if (result > 0) {
return true;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return false;
}
}
(5)UsersService接口
package com.etc.aop.service;
import com.etc.aop.entity.Users;
public interface UsersService {
public boolean addUsers(Users user);
}
(6)UsersService接口的实现类UsersServiceImpl
package com.etc.aop.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.etc.aop.dao.UsersDao;
import com.etc.aop.entity.Users;
import com.etc.aop.service.UsersService;
@Service(value="us")
public class UsersServiceImpl implements UsersService {
@Autowired
private UsersDao ud;
@Override
public boolean addUsers(Users user) {
return ud.addUsers(user);
}
}
(7)切面类(环绕通知,进行日志记录)
package com.etc.aop.log;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import com.etc.aop.entity.Users;
@Component
@Aspect
public class LogAop {
@Around(value="execution(* com.etc.aop.dao.impl.*.*(..))")
public Object writeLog(ProceedingJoinPoint pjp) throws Throwable {
Object obj = pjp.proceed();
boolean flag = Boolean.parseBoolean(obj.toString());
System.out.println("aop flag="+flag);
Object[] objs = pjp.getArgs();
FileWriter fw = new FileWriter("log.txt",true);
//将Date类对象格式化成字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss ");
String dateStr = sdf.format(new Date());
String username = ((Users)objs[0]).getUsername();
if(flag) {
fw.append(dateStr+"--"+username+"-- 注册成功\r\n");
}else {
fw.append(dateStr+"--"+username+"-- 注册失败\r\n");
}
fw.close();
return obj;
}
}
(8)测试类
package com.etc.aop.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.etc.aop.entity.Users;
import com.etc.aop.service.UsersService;
@SpringJUnitConfig(locations="classpath:springaop.xml")
public class TestRegister {
@Autowired
UsersService us;
@Test
public void test() {
Users user= new Users(180, "tom", "1234");
boolean flag = us.addUsers(user);
System.out.println("test flag="+flag);
}
}
(9)Spring全局配置文件:springaop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 使用aop有关的注解支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 关于IOC注解支持配置 -->
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.etc.aop"></context:component-scan>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="url" value="jdbc:mysql://localhost:3306/userdb?serverTimezone=Asia/Shanghai"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
</bean>
</beans>