文章目录
框架前言
名词辨析
技术、组件、框架、系统
技术:解决某一类问题的方法和手段,jdbc技术,jsp技术
组件:应用程序中可以复用的“零件”(封装的类库),分页组件,数据库访问组件
框架:Framework,是构成一组特定软件可复用设计的一组相互协助工作的类,是一个程序的半成品。生活中的简历模板,盖房子,钢构结构,活动板房。
系统:实现了完整功能的应用程序,淘宝系统,网上交易系统。
JavaWeb阶段回顾
程序主要处理的就是数据,数据通常会被存储在数据库(MySQL、Oracle、NoSQL)或内存中。
Java和数据库的操作:Sun公司提供的JDBC接口规范API,具体的接口实现由各家数据库厂商实现。
传统JDBC如何操作数据库?
加载驱动
Class.forName("com.mysql.jdbc.Driver");
获取连接
DriverManager.getConnection(url, username, password);
创建执行对象
conn.prepareStatement("sql");
进行CRUD操作--->解析结果集
ps.setXXX()/ps.executeUpdate()/ps.executeQuery()/while(rs.next()) rs.getXXX("列名")
释放连接
底层抛出异常,高层抓取异常。
(DAO层抛出异常)
从JavaWeb阶段的学习,我们可以发现
DAO模块:
- DAO模块中为了要释放连接,普遍都是try-finally代码块;
- SQL代码与Java代码耦合;
- SQL的参数设置,preparedStatement.setXxx(),有些繁琐;
- SQL作为字符串形式写在参数中,可读性差,尤其是当SQL是复杂SQL时,连接查询、子查询等;
- 读取结果集时设置对象参数复杂,如果对象属性(表的字段)有特别多时,逐一setXxx(rs.getXxx())不现实;
- 每次查询都是物理查询,没有缓存的功能
综合所述,参数映射、结果集映射、缓存、多表连接查询等等问题如果实现了,那将不简单是技术,而是框架。
Controller模块:
- Servlet读取浏览器、表单参数过程复杂;
- 一个Servlet只能处理一个请求/多个urlPatterns,导致Servlet过多;
- Servlet支持的视图类型:html、jsp;不支持json;
- …
框架介绍
前端:
js:jquery,vue
h5:bootstrap
Spring:
Spring贯穿整个应用程序,也就是后台三层中都是使用到了spring,IOC,AOP,萌芽2000年,诞生于2004年
Servlet:
MVC框架
SpringMVC(最优秀的mvc框架),Spring的后续产品2005年
Struts(退出舞台了) Struts2(奄奄一息,老系统还要维护) 2000年产物
DAO:
Mybatis(互联网项目很流行)2010年,早期ibatis,后来google,更名为Mybatis 2013
Hibernate(老系统在维护,或者新的系统但不怎么更改更新)
SSH-> Spring + Struts2 + Hibernate
SSM-> Spring + SpringMVC + Mybatis
前面都是基础,后面才能学习
Spring Boot :简化Spring开发的,SSM做一个查询,需要30分钟,Spring Boot只需要5分钟不到,2014年
Spring Colud:微服务一站式框架,架构
ORM框架
ORM(Object Relational Mapper)对象关系映射。
O—>Java对象
R—>数据库表
M—>映射文件
一个Java类对应数据库中的一张表;
一个Java属性对应数据库中的一个字段;
一个Java对象对应数据库中的一个对象。
MyBatis简介
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis入门案例
MyBatis入门版CRUD
1、环境准备
CREATE DATABASE mybatis;
USE mybatis;
CREATE TABLE account (
aid INT PRIMARY KEY AUTO_INCREMENT,
aname VARCHAR(20) NOT NULL,
apassword VARCHAR(20) NOT NULL,
a_nickname VARCHAR(20) NOT NULL
);
INSERT INTO account VALUES(NULL, 'zhangsan', 'nasgnahz', '张三');
INSERT INTO account VALUES(NULL, 'lisi', 'isil', '李四');
IDEA 2020.1
JDK 1.8
Maven 3.6.3
2、新建普通Maven项目,导入依赖
MyBatis最新版本:3.5.5
数据库驱动:5.1.47
Lombok:简化POJO类的开发
Junit:测试Mapper。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.westos</groupId>
<artifactId>20200901-mybatis-HelloWorld</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3、MyBatis核心配置文件
模板:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
位置放在src/main/resources目录下,编译后位于target/classes类路径下。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--一个程序可能操作多个数据源(数据库),而且开发环境和本地测试环境也不一样,所以这里为environments-->
<environments default="development">
<!--其中一个数据源-->
<environment id="development">
<!--事务管理,用的是JDBC的事务管理-->
<transactionManager type="JDBC"/>
<!--数据源,type="POOLED",连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="995995zxvc"/>
</dataSource>
</environment>
</environments>
<!--<mappers>
<mapper resource="org/westos/mapper/AccountMapper.xml"/>
</mappers>-->
</configuration>
这里mappers标签还未完成,并且datasource数据源为强耦合,未拆分为properties文件。
注意事项:
- 在xml中配置数据源中的url属性时,当后面的连接参数有多个时,&需要转义,
&
; - 在properties中配置数据源中的url属性时,当后面的连接参数有多个时,&不需要转义。
4、POJO类Account对应数据表account
package org.westos.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* model包也可
* @author lwj
* @date 2020/9/1 20:01
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account implements Serializable {
private static final long serialVersionUID = 5207905760950301832L;
private Integer aid;
private String aname;
private String apassword;
/*在数据库中字段为a_nickname*/
private String anickname;
}
5、Mapper映射文件
这个XXXMapper.xml映射文件,可以放在src/main/resources目录下,也可以放在src/main/java/目录下,他们最终都是要在核心配置文件mybatis-config.xml中的mappers标签下引入的。
区别在于,默认情况下,maven在编译打包时,对于src/main/java目录只编译源代码,不会编译其他文件,这就会导致编译后的target/classes目录下不存在XXXMapper.xml,而导致在核心配置文件中找不到该映射文件,解决办法是在pom.xml中配置build标签;如果放在src/main/resources则不会有这种情况。
这次我是放在src/main/java目录下,配置build标签。
Mapper.xml的模板代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.westos.mapper.AccountMapper">
<!--命名空间,一般与Mapper接口同名,各个id与Mapper接口中的方法同名-->
<!--初学阶段没有写Mapper接口,后期使用Mapper接口 + 代理类的方式-->
<!--在测试时,将namespace + id放到参数中即可-->
<select id="selectAll" resultType="org.westos.pojo.Account">
select *
from
account
</select>
</mapper>
pom.xml
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
将AccountMapper.xml映射文件在mybatis-config.xml中引入。
<mappers>
<mapper resource="org/westos/mapper/AccountMapper.xml"/>
</mappers>
compile后,
6、Junit测试
在src/test/java目录下测试。
新建AccountMapperTest类。
package org.westos.mapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.westos.pojo.Account;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author lwj
* @date 2020/9/1 20:11
*/
public class AccountMapperTest {
@Test
public void selectAll() throws IOException {
//1、读取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3、创建SqlSession,openSession()默认事务是手动提交,所以在增删改时需要提交事务
SqlSession sqlSession = factory.openSession();
//4、查询封装
List<Account> list = sqlSession.selectList("org.westos.mapper.AccountMapper.selectAll");
//5、输出
System.out.println(list);
//6、关闭Session
sqlSession.close();
}
}
结果:由于Account类的anickname和account表的a_nickname不能匹配,所以不能赋值。
[
Account(aid=1, aname=zhangsan, apassword=nasgnahz, anickname=null),
Account(aid=2, aname=lisi, apassword=isil, anickname=null)
]
maven管理测试类必须先用maven test,在target目录中生成编译类才可以进行测试。
从结果中可以看到,并没有封装与数据库表account中a_nickname字段不对应的anickname属性。
解决办法:用别名,因为框架在查询封装时,使用的也是别名,比如JDBC中的Metadata中的getColumnLabel()。
ResultSetMetaData metaData = resultSet.getMetaData();
String columnLabel = metaData.getColumnLabel(1);
//最关键,getColumnLabel 获取字段别名,和属性一致,即可匹配
<select id="selectAll" resultType="org.westos.pojo.Account">
select aid, aname, apassword, a_nickname anickname
from
account
</select>
修改SQL后的查询结果:
[
Account(aid=1, aname=zhangsan, apassword=nasgnahz, anickname=张三),
Account(aid=2, aname=lisi, apassword=isil, anickname=李四)
]
我们发现mybatis中sql是编写在mapper.xml配置文件中的,这样做的好处是sql代码和java代码相分离,便于sql的维护,更改sql,也不需要重新编译。
在查询完毕后,mybatis自动的将查询结果和java对象进行了关联,且是集合类型。
7、根据id查询
AccountMapper.xml
<select id="selectById" resultType="org.westos.pojo.Account">
select aid, aname, apassword, a_nickname anickname
from account
where aid = #{aid}
</select>
AccountMapperTest.java
public class AccountMapperTest {
SqlSessionFactory factory = null;
SqlSession sqlSession = null;
@Before
public void before() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(in);
}
@Test
public void selectById() {
sqlSession = factory.openSession();
Account account = sqlSession.selectOne("org.westos.mapper.AccountMapper.selectById", 1);
System.out.println(account);
}
@After
public void after() {
if (sqlSession != null) {
sqlSession.close();
}
}
}
查询结果:
Account(aid=1, aname=zhangsan, apassword=nasgnahz, anickname=张三)
8、增
AccountMapper.xml
<!--下面insert语句中的#{}为对象的属性-->
<insert id="insert">
insert into
account(aname, apassword, a_nickname)
values(#{aname}, #{apassword}, #{anickname})
</insert>
AccountMapperTest.java
@Test
public void insert() {
sqlSession = factory.openSession();
Account account = new Account();
account.setAname("wangwu");
account.setApassword("uwgnaw");
account.setAnickname("王五");
int insert = sqlSession.insert("org.westos.mapper.AccountMapper.insert", account);
sqlSession.commit();
//提交事务
}
9、改
AccountMapper.xml
<update id="update">
update
account
set
aname = #{aname}, apassword = #{apassword}, a_nickname = #{anickname}
where
aid = #{aid}
</update>
AccountMapperTest.java
@Test
public void update() {
sqlSession = factory.openSession();
Account account = new Account();
account.setAid(3);
account.setAname("zhaoliu");
account.setApassword("uiloahz");
account.setAnickname("赵六");
int update = sqlSession.update("org.westos.mapper.AccountMapper.update", account);
sqlSession.commit();
}
10、删
AccountMapper.xml
<delete id="delete">
delete
from account
where
aid = #{aid}
</delete>
AccountMapperTest.java
@Test
public void delete() {
sqlSession = factory.openSession();
int delete = sqlSession.delete("org.westos.mapper.AccountMapper.delete", 3);
sqlSession.commit();
}
11、mapper.xml放在resources目录下
将XXXmapper.xml放在resources和DAO接口相同的目录下。
将XXXmapper.xml放在resources目录下就不用在pom.xml中设置build标签。
maven的compile命令默认会把src/main/resources下的所有配置文件以及src/main/java下的所有java文件打包或发布到target\classes下面。