一、xml方式实现
1.介绍lombok插件
dbUtil-阿帕奇提供操作数据库的插件
2.功能
对实体类自动,动态生成getset,无参有参 toString.....
3.步骤
3.1 idea安装插件(只做一次)
3.2 添加坐标
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
3.3 编写注解
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Account implements Serializable {
private int aid;
private String aname;
private int amoney;
public Account(String aname, int amoney) {
this.aname = aname;
this.amoney = amoney;
}
}
4.核心类
4.1 QueryRunner
//操作数据库的核心类
QueryRunner queryRunner;
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
4.2 query() 查询
@Override
public void save(Account account) {
try {
queryRunner.update("insert into account(aname,amoney) value(?,?)",account.getAname(),account.getAmoney());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Override
public void updateById(Account account) {
try {
queryRunner.update("udpate account set aname=?,amoney=? where aid=?",account.getAname(),account.getAmoney(),account.getAid());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Override
public void deleteById(int id) {
try {
queryRunner.update("delete from account where aid=?",id);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
4.3 update() 增删改
@Override
public Account findByName(String name) {
try {
return queryRunner.query("select * from account where aname=?",new BeanHandler<Account>(Account.class),name);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
@Override
public List<Account> findAll() {
try {
return queryRunner.query("select * from account",new BeanListHandler<Account>(Account.class));
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
5.配置文件applicationContext.xml
<!--加载资源文件-->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<!--注入数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${msg1}"></property>
<property name="jdbcUrl" value="${msg2}"></property>
<property name="user" value="${msg3}"></property>
<property name="password" value="${msg4}"></property>
</bean>
<!--注入QueryRunner-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!--注入dao-->
<bean id="mapperImp" class="com.ztt.dao.AccountMapperImp">
<property name="queryRunner" ref="queryRunner"></property>
</bean>
<!--注入service-->
<bean id="service" class="com.ztt.service.AccountServiceImp">
<property name="mapper" ref="mapperImp"></property>
</bean>
<!--注入controller-->
<bean id="controller" class="com.ztt.controller.AccountControllerImp">
<property name="service" ref="service"></property>
</bean>
6.junit测试
6.1使用步骤
6.1.1 坐标
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--数据源-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
6.1.2 注解(修饰方法)
@Test======>可以运行的方法
@Before====>@Test运行之前
@After=====>@Test运行之后
方式一:
public class Test01 {
ClassPathXmlApplicationContext applicationContext =null;
IAccountController controller = null;
@Before
public void beforeMethod(){
applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
controller = (IAccountController) applicationContext.getBean("controller");
}
@After
public void afterMethod(){
applicationContext.close();
}
@Test
public void show1(){
controller.save(new Account("张甜甜",2000));
controller.save(new Account("许娜",2000));
}
@Test
public void show2(){
List<Account> all = controller.findAll();
for (int i = 0; i < all.size(); i++) {
Account account = all.get(i);
System.out.println(account);
}
}
}
方式二:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test02 {
@Autowired
IAccountController controller;
@Test
public void show1(){
controller.save(new Account("张甜甜",2000));
controller.save(new Account("许娜",2000));
}
@Test
public void show2(){
List<Account> all = controller.findAll();
for (int i = 0; i < all.size(); i++) {
Account account = all.get(i);
System.out.println(account);
}
}
@Test
public void show3(){
controller.transfer("张甜甜","许娜",100);
}
}
二、annotation注解方式实现
1.控制层(cotroller)
@Controller("controller")
public class AccountControllerImp implements IAccountController {
@Autowired
IAccountService service;
2.业务层(service)
@Service
public class AccountServiceImp implements IAccountService{
@Autowired
IAccountMapper mapper;
3.数据访问层(dao)
@Repository
public class AccountMapperImp implements IAccountMapper{
//操作数据库的核心类
@Autowired
QueryRunner queryRunner;
4.配置文件applicationContext.xml
<!--加载资源文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--注入数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${msg1}"></property>
<property name="jdbcUrl" value="${msg2}"></property>
<property name="user" value="${msg3}"></property>
<property name="password" value="${msg4}"></property>
</bean>
<!--注入QueryRunner-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!--扫描-->
<context:component-scan base-package="com.ztt"></context:component-scan>
测试类同上
三、configuration配置类方式实现
在三层框架的基础上新建一个包config,用来写配置类
1.ApplicationConfig
@Configuration
@ComponentScan(basePackages = "com.ztt")
@Import(DataConfig.class)
public class ApplicationConfig {
}
2.DataConfig 替换applicationContext.xml
@Configuration
@PropertySource(value = "classpath:jdbc.properties")
public class DataConfig {
@Value("${msg1}")
private String driverClass;
@Value("${msg2}")
private String jdbcUrl;
@Value("${msg3}")
private String user;
@Value("${msg4}")
private String password;
// <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
// <property name="driverClass" value="${msg1}"></property>
// <property name="jdbcUrl" value="${msg2}"></property>
// <property name="user" value="${msg3}"></property>
// <property name="password" value="${msg4}"></property>
// </bean>
@Bean
public DataSource dataSource(){
try {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setDriverClass(driverClass);
comboPooledDataSource.setJdbcUrl(jdbcUrl);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
return comboPooledDataSource;
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return null;
}
// <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
// <constructor-arg name="ds" ref="dataSource"></constructor-arg>
// </bean>
@Bean
public QueryRunner queryRunner(){
return new QueryRunner(dataSource());
}
}
3.测试类
四、在xml基础上实现转账业务
目的:业务层进行事务管理
1.同一个业务方法的多个dao方法公用一个connection对象
2.ThreadLocal
3.通过连接对象进行事务的统一管理
ConnectionUtil连接工具类:
public class ConnectionUtil {
//装配数据源
DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
//线程区域对象
ThreadLocal<Connection> threadLocal=new ThreadLocal<Connection>();
//获取连接
public Connection createCon(){
Connection connection = null;
try {
//1.获取线程内的连接对象
connection=threadLocal.get();
//2.判断
if(connection==null){
connection=dataSource.getConnection();//创建连接
threadLocal.set(connection);//保存
}
return connection;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
//移除连接
public void removeCon(){
threadLocal.remove();//移除连接
}
}
TransactionUtil事务管理工具类:
public class TransactionUtil {
//注入连接工具类
ConnectionUtil connectionUtil;
public void setConnectionUtil(ConnectionUtil connectionUtil) {
this.connectionUtil = connectionUtil;
}
//开启事务
public void beginTx(){
try {
connectionUtil.createCon().setAutoCommit(false);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//提交事务
public void commitTx(){
try {
connectionUtil.createCon().commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//回滚事务
public void rollbackTx(){
try {
connectionUtil.createCon().rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//关闭事务
public void closeTx(){
try {
connectionUtil.createCon().close();//关闭事务
connectionUtil.removeCon();//移除事务
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
AccountMapperImp:
public class AccountMapperImp implements IAccountMapper{
//操作数据库的核心类
QueryRunner queryRunner;
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
//注入连接工具
ConnectionUtil connectionUtil;
public void setConnectionUtil(ConnectionUtil connectionUtil) {
this.connectionUtil = connectionUtil;
}
AccountServiceImp:
public class AccountServiceImp implements IAccountService{
IAccountMapper mapper;
public void setMapper(IAccountMapper mapper) {
this.mapper = mapper;
}
//装配
TransactionUtil transactionUtil;
public void setTransactionUtil(TransactionUtil transactionUtil) {
this.transactionUtil = transactionUtil;
}
@Override
public void transfer(String sourceName, String targetName, int money) {
try {
transactionUtil.beginTx();
//1.查询数据
Account sourceAccount = mapper.findByName(sourceName);
Account targetAccount = mapper.findByName(sourceName);
//2.转账
sourceAccount.setAmoney(sourceAccount.getAmoney()-money);
targetAccount.setAmoney(targetAccount.getAmoney()+money);
//3.修改数据库
mapper.updateById(sourceAccount);
int a=10/0;//模拟异常
mapper.updateById(targetAccount);
transactionUtil.commitTx();
} catch (Exception e) {
e.printStackTrace();
transactionUtil.rollbackTx();
} finally {
transactionUtil.closeTx();
}
}
AccountControllerImp:
public class AccountControllerImp implements IAccountController {
IAccountService service;
public void setService(IAccountService service) {
this.service = service;
}
@Override
public void transfer(String sourceName, String targetName, int money) {
service.transfer(sourceName,targetName,money);
}
public void save(Account account) {
service.save(account);
}
配置文件applicationContext.xml
在原有的基础上注入连接工具类、事务工具类、以及在业务层注入事务管理工具类
<!--连接工具类-->
<bean id="connectionUtil" class="com.ztt.util.ConnectionUtil">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务工具类-->
<bean id="transactionUtil" class="com.ztt.util.TransactionUtil">
<property name="connectionUtil" ref="connectionUtil"></property>
</bean>
<!--注入dao-->
<bean id="mapperImp" class="com.ztt.dao.AccountMapperImp">
<property name="queryRunner" ref="queryRunner"></property>
</bean>
<!--注入service-->
<bean id="service" class="com.ztt.service.AccountServiceImp">
<property name="mapper" ref="mapperImp"></property>
<property name="transactionUtil" ref="transactionUtil"></property>
</bean>
<!--注入controller-->
<bean id="controller" class="com.ztt.controller.AccountControllerImp">
<property name="service" ref="service"></property>
</bean>
测试方法:
@Test
public void show3(){
controller.transfer("张甜甜","许娜",100);
}
5.项目总结:
1.事务管理应该由service层进行实现
代码优化:
目的:业务层进行事务管理
1.同一个业务方法的多个dao方法公用一个connection对象
2.ThreadLocal
3.通过连接对象进行事务的统一管理
五、设计模式
1.JAVA六大设计原则
JAVA设计模式提供六个基本原则,分别是:
- 开闭原则(OCP) - The Open-Closed Principle
- 单一职责原则(SRP) - Single Responsibility Principle
- 里氏替换原则(LSP) - Liskov Substitution Principle
- 依赖倒置原则(DIP) - Dependency Inversion Principle
- 接口隔离原则(ISP) - Interface Segregation Principle
- 迪米特法则(DP) - Demeter Principle
2.JAVA23种设计模式
在软件工程当中,设计原则和设计模式是不同的.
3.设计原则
设计原则是为了更好的设计软件的高层指导方针.
它不提供具体的实现方式也不会绑定任何一种编程语言.
最常用的原则是SOLID(SRP, OCP, LSP, ISP, DIP)原则
4.设计模式
设计模式对关于面向对象问题的具体解决方案.
比如说, 如果你想创建一个类而且它在任何时刻只会有一个对象,那么你就应该使用单例类模式.
设计模式是经过大量检测的安全的做法.
4.1 工厂模式(factory)
案例:
INoodles:
package com.ztt.test;
public interface INoodles {
public void noodleType();
}
LanZhouLaMianImp:
package com.ztt.test;
public class LanZhouLaMianImp implements INoodles{
@Override
public void noodleType() {
System.out.println("========来一碗兰州拉面========");
}
}
ReGanMianNoodleImp:
package com.ztt.test;
public class ReGanMianNoodleImp implements INoodles{
@Override
public void noodleType() {
System.out.println("========来一碗武汉热干面========");
}
}
YouPoMianNoodleImp:
package com.ztt.test;
public class YouPoMianNoodleImp implements INoodles{
@Override
public void noodleType() {
System.out.println("========来一碗油泼面========");
}
}
NoodleFactory:
package com.ztt.test;
/**
* 面长
* */
public class NoodleFactory {
/**
* 规范下面条类型
* */
public static final int NOODLE_YOUPO = 1;
public static final int NOODLE_REGAN = 2;
public static final int NOODLE_LANZHOULA = 3;
/**
*创建面条
**/
public static INoodles getNoodle(int type){
if (type == 1){
return new YouPoMianNoodleImp();
}else if(type ==2){
return new ReGanMianNoodleImp();
}else if(type ==3 ){
return new LanZhouLaMianImp();
}
return null;
}
}
package com.ztt.test;
public class Test01 {
public static void main(String[] args) {
NoodleFactory.getNoodle(NoodleFactory.NOODLE_LANZHOULA).noodleType();
NoodleFactory.getNoodle(3).noodleType();
}
}
4.2 单列设计模式(singlton)
饿汉式:
package com.ztt.hungrytest;
/**
* 饿汉式
* */
public class Student {
//3.创建static修饰的成员变量
private static Student stu = new Student();
//1.设计私有构造方法
private Student(){
super();
}
//2.提供共有的方法
public static synchronized Student getInstance(){
return stu;
}
}
package com.ztt.hungrytest;
import com.ztt.lazytest.Student;
public class Test03 {
public static void main(String[] args) {
com.ztt.lazytest.Student stu1 = com.ztt.lazytest.Student.getInstance();
Student stu2 = Student.getInstance();
System.out.println(stu1== stu2);
}
}
懒汉式:
package com.ztt.lazytest;
/**
* 懒汉式
* */
public class Student {
//3.创建static修饰的成员变量
private static Student stu;
//1.设计私有构造方法
private Student(){
super();
}
//2.提供共有的方法
public static synchronized Student getInstance(){
if(stu == null){
stu = new Student();
}
return stu;
}
}
package com.ztt.lazytest;
public class Test02 {
public static void main(String[] args) {
Student stu1 = Student.getInstance();
Student stu2 = Student.getInstance();
System.out.println(stu1== stu2);
}
}
六、代理模式
1.什么是代理模式?
- 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
- 通俗的来讲代理模式就是我们生活中常见的中介。
- 举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,
- 做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。
- 我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介
- 公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择
- 自己喜欢的车,然后付钱就可以了。
2.为什么要用代理模式?
2.1 中介隔离作用:
在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
2.2 开闭原则,增加功能:
代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。
3.有哪几种代理模式?
我们有多种不同的方式来实现代理。如果按照代理创建的时期来进行分类的话可以分为两种:
3.1 静态代理:
静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。
在程序员运行之前,代理类.class文件就已经被创建了。
3.2 动态代理:
动态代理是在程序运行时通过反射机制动态创建的。
动态代理分为:
- 基于接口的动态代理(jdk自带)
- 基于子类的动态代理(第三方)
静态代理案例:
package com.ztt.statictest;
public interface IWonman {
public void makeEyeWithMan();
}
package com.ztt.statictest;
public class PanJinLianImp implements IWonman{
@Override
public void makeEyeWithMan() {
System.out.println("回眸一笑,抛个媚眼~");
}
}
package com.ztt.statictest;
//代理
public class WangPoImp implements IWonman{
//被代理对象
IWonman obj;
public WangPoImp(IWonman obj) {
this.obj = obj;
}
@Override
public void makeEyeWithMan() {
System.out.println("镇一壶酒,搞搞气氛~");
obj.makeEyeWithMan();
}
}
package com.ztt.statictest;
public class XiMenQingTest {
public static void main(String[] args) {
//1.创建被代理对象
IWonman pan = new PanJinLianImp();
//2.创建代理
IWonman wang = new WangPoImp(pan);
wang.makeEyeWithMan();
}
}