框架
一、什么是框架
框架(Framework)是整个或者部分系统的可重用设计,表现为一组抽象构件及构件实例之间交互的方法,另一种定义认为,框架是可被应用发开者订制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
简而言之,框架其实就是某种半成品软件,就是一组组件,供你选用完成你自己的系统。再简而言之就是别人搭好的舞台,你要做的就是在上面表演。
使用框架的好处:框架封装了很多的细节,使开发者可以使用极简的方式
二、三层架构和SSM框架的对应关系
三层框架
表现层: 用于展示数据 SpringMVC框架:表现层框架 Servlet:封装数据 JSP:视图 域对象
业务层: 用于处理业务需求 Service:业务逻辑处理 JavaBean数据模型
持久层: 用于和数据库交互 MyBatis框架:持久层框架 DAO
三、持久层技术解决方案
JDBC技术:
? Connection
? PreparedStatement
? ResultSet
Spring的JdbcTemplate:
? Spring中对jdbc的简单封装
Apache的DBUtils:
? 和Spring的JdbcTemplate很像,也是对Jdbc的简单封装
以上这些都不是框架:Spring的JdbcTemplate和Apache的DBUtils都只是工具类
四、MyBatis框架
mybatis框架是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动,创建连接、创建statement等复杂的过程。
mybatis通过xml或者注解的方式将要执行的各种statment配置起来,并通过java对象和statment中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。
采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用于jdbc api打交道,就可以完成对数据库的持久化操作。
ORM: object relational mapping 对象关系映射 简单来说:就是把数据库表和实体类及实体类的属性对应起来 让我们可以操作实体类就实现操作数据库表。 我们需要做到实体类中的属性和数据库表的字段名保持一致。
1.MyBatis的入门
1.1 MyBatis的环境搭建
? 第一步:创建maven工程并导入坐标
? 第二步:创建实体类和dao接口
? 第三步:创建Mybatis的主配置文件 sqlMapConfig.xml
? 第四步:创建映射配置文件 IUserDao.xml
环境搭建的注意事项:
? 1.创建IUserDao和IUserDao.java时名称是为了和我们之前的知识保持一致,在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper。所以IUserDao和IUserMapper是一样的
? 2.在idea中创建目录的时候和包是不一样的,包在创建时通过.是下级创建,目录在创建时.没用,只有一级目录
? 3.mybatis的映射配置文件位置必须和dao接口的包结构相同。
? 4.映射配置文件的Mapper标签namespace属性的取值必须是dao接口的全限定类名
? 5.映射配置文件的操作配置,id属性的取值必须是dao接口的方法名
当遵从了345点之后,在开发中就无须再写dao的实现类。
1.2 MyBatis的入门案例
这里实现一个将数据库中表的内容封装到成java对象并打印的案例。
1.首先创建一个空的maven工程,导入mybatis、mysql、junit、log4j依赖。
<?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>com.tcj</groupId>
<artifactId>Mybatis01_maven</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.13</version>
</dependency>
</dependencies>
</project>
2.创建数据库,再创建一张表,我这里使用day14数据库user表
CREATE DATABASE day14;
DROP TABLE IF EXISTS USER;
CREATE TABLE USER(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL COMMENT '用户名称',
birthday DATETIME DEFAULT NULL COMMENT '生日',
sex CHAR(1) DEFAULT NULL COMMENT '性别',
address VARCHAR(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (id)
)ENGINE = INNODB DEFAULT CHARSET=utf8;
INSERT INTO USER VALUES(43,'小二王','2018-02-27 17:47:08','女','陕西西安'),
(44,'小二王','2018-03-27 17:47:08','男','陕西西安'),
(45,'张三','2018-06-27 17:47:08','男','陕西宝鸡'),
(46,'mybatis last insertid','2018-07-27 17:47:08','男','四川成都'),
(47,'dao impl user','2018-03-27 17:47:08','男','陕西西安');
3.在src/main/java/com/tcj/domain下创建UserBean
package com.tcj.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private int id;
private String username;
private Date birthday;
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 +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
4.在src/main/resources目录下创建一个全局的xml文件,我这里使用SqlMapConfig.xml命名
<?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="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/day14"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/tcj/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
5.在src/main/java/com/tcj/dao下创建UserDao接口,实现跟查询数据库的方法;
package com.tcj.dao;
import com.tcj.domain.User;
import java.util.List;
public interface IUserDao {
List<User> findAll();
}
5.在resources资源目录下创建与java目录相同的目录路径,并且创建映射配置文件。src/main/resources/com/tcj/dao/IUserDao.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="com.tcj.dao.IUserDao">
<select id="findAll" resultType="com.tcj.domain.User">
select * from user
</select>
</mapper>
注意:resultType=“com.tcj.domain.User”,就是User类的全类名。
6.在test目录下创建测试类:src/test/java/com/tcj/mybatis/MybataisTest.java
package com.tcj.mybatis;
import com.tcj.dao.IUserDao;
import com.tcj.domain.User;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybataisTest {
public static void main(String[]args) throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder =new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
IUserDao userDao = session.getMapper(IUserDao.class);
List<User> users = userDao.findAll();
for (User user : users){
System.out.println(user);
}
session.close();
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
7.最终结果:
==> Preparing: select * from user
==> Parameters:
<== Total: 6
User{id=42, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='陕西西安'}
User{id=43, username='小二王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='女', address='陕西西安'}
User{id=44, username='小二王', birthday=Tue Mar 27 17:47:08 CST 2018, sex='男', address='陕西西安'}
User{id=45, username='张三', birthday=Wed Jun 27 17:47:08 CST 2018, sex='男', address='陕西宝鸡'}
User{id=46, username='李四', birthday=Fri Jul 27 17:47:08 CST 2018, sex='男', address='四川成都'}
User{id=47, username='王五', birthday=Tue Mar 27 17:47:08 CST 2018, sex='男', address='陕西西安'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3159c4b8]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3159c4b8]
Returned connection 827966648 to pool.
Process finished with exit code 0
总结:
? 1.读取配置文件
? 2.创建SqlSessionFactory工厂
? 3.创建SqlSession
? 4.创建Dao连接的代理对象
? 5.执行dao中的方法
? 6.释放资源
注意事项: 不要忘记在映射配置中告知mybatis要封装到哪个实体类中 配置的方式:指定实体类的全限定类名。
1.3 MyBatis注解开发和dao实现类
<mappers>
<mapper class="com.tcj.dao.IUserDao"/>
</mappers>
可以将映射配置文件。src/main/resources/com/tcj/dao/IUserDao.xml删除
明确:
我们在实际开发中都是约简便越好,所以都是采用不写dao实现类的方式。不管使用xml还是注解配置。但是MyBatis它是支持写dao实现类的。
2. 自定义MyBatis的分析
mybatis在使用代理dao的方式实现增删改查时做什么事?
? 1.创建代理对象
? 2.在代理对象中调用selectList方法
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/day14"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
上面是连接数据库的信息,有了它可以创建Connection对象
<mapper resource="com/tcj/dao/IUserDao.xml"></mapper>
有了就有了映射配置信息
<mapper namespace="com.tcj.dao.IUserDao">
<select id="findAll" resultType="com.tcj.domain.User">
select * from user
</select>
</mapper>
有了它就有了执行的SQL语句,就可以获取PreparedSatement。同时,此配置中还有封装的实体类全限定类名。
**最主要:**读取配置文件:用到的技术就是解析XML的技术。此处用到的是dom4j解析xml技术。
当我们删除了mybatis依赖之后,自己通过编写实现类,实现已提供给我们的mybatis框架的方法,进而理解mybatis框架执行的原理。
3.MyBatis的CRUD操作
3.1 查询所有操作
xml方式实现:
1.编写IUserDao接口中的方法
List<User> findAll();
2.在IUserDao.xml中添加select标签
<select id="findAll" resultType="com.tcj.domain.User">
select * from user
</select>
3.在Test测试类中执行测试方法。主要是使用代理对象执行方法
package com.tcj.mybatis;
import com.tcj.dao.IUserDao;
import com.tcj.domain.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybataisTest {
private InputStream in;
private SqlSession session;
private IUserDao userDao;
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder =new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
session = factory.openSession();
userDao = session.getMapper(IUserDao.class);
}
@After
public void close() throws IOException {
session.close();
in.close();
}
@Test
public void thestFindAll() throws IOException {
List<User> users = userDao.findAll();
for (User user : users){
System.out.println(user);
}
}
注解方式实现:
用注解的方式就不需要使用IUserDao.xml文件了
1.在IUserDao接口中编写findAll()方法。并且添加Select注解
@Select("select * from user")
List<User> findAll();
这里的"select * from user"就是之前IUserDao.xml文件的标签体内容
2.直接在Test测试方法中调用
@Test
public void thestFindAll() throws IOException {
List<User> users = userDao.findAll();
for (User user : users){
System.out.println(user);
}
}
3.2 保存用户信息到数据库操作
xml方式实现:
1.编写IUserDao接口中的方法
void saveUser(User user);
2.在IUserDao.xml中编写insert标签
<insert id="saveUser" parameterType="com.tcj.domain.User">
insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})
</insert>
标签体中的#{xxx}即我们以前学的sql中的通配符号? 这里是mybatis的写法,我们需要注意的是xxx是与User实体类中的get和set方法后面的属性对应的。 parameterType即参数类型:给定User类中的参数转为sql语句中的字符串。我们这里就是User类。
3.在测试类中测试方法
@Test
public void saveUserTest() throws Exception {
User user = new User();
user.setUsername("mybatis saveuser");
user.setAddress("四川省成都市金牛区九里堤街道");
user.setSex("男");
user.setBirthday(new Date());
userDao.saveUser(user);
session.commit();
}
注解方式实现:
1.直接在IUserDao接口中定义方法
@Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
void saveUser(User user);
这里需要添加insert注解,内容即之前xml文件中的标签体内容。
2.测试
@Test
public void saveUser(){
User user = new User();
user.setUsername("mybatis saveuser 用注解方式");
user.setAddress("四川省成都市金牛区九里堤街道");
user.setSex("男");
user.setBirthday(new Date());
userDao.saveUser(user);
}
这里没有写session.commit()是因为在之前已经在@After中写过了
3.3 更改用户信息到数据库操作
xml方式:
1.在IUserDao接口中添加方法
**
* 更新用户
* @param user
*/
void updateUser(User user);
2.在IUserDao.xml中添加update标签
<update id="updateUser" parameterType="com.tcj.domain.User">
update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}
</update>
为什么这样写原因见3.2 xml方式。
注解方式:
1.在IUserDao接口中添加方法
@Update("update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}")
void updateUser(User user);
2.测试
@Test
public void updateUser(){
User user = new User();
user.setId(50);
user.setUsername("mybatis updateUser 用注解方式");
user.setAddress("四川省成都市金牛区");
user.setSex("男");
user.setBirthday(new Date());
userDao.updateUser(user);
}
|