框架的介绍
框架的搭配
SSH:Spring,Struts2,Hibernate
SSM:Spring,SpringMVC ,Mybatis
什么是框架
框架也是一个项目,但是他是一个半成品,框架给我们提供了很多功能,我们需要使用这些功能。
学习框架:学习这些功能怎么使用,了解他们底层实现,学习API(方法)。
Jar包导入方式
方式一:手动导入
去官网中下载
一般情况下,框架会提供案例,去案例中拷贝。
方式二:maven导入(推荐的)
编写对应jar的 坐标,自动导入、以及jar包所需的依赖。
Mybatis介绍
回顾总结JDBC中存在的问题
(1)数据库连接,使用的时候就创建,不使用是否连接,对数据进行频繁开启与关闭,造成数据库资源的浪费,影响性能。
解决方案:使用数据库连接池去管理数据库连接
(2)将SQL语言 硬编码 到Java代码中,如果SQL语言有变化,需要重新编译Java代码,不利于系统维护。
解决方案:将SQL语句放到XML配置文件中,即使SQL语句有变化,不需要对Java代码重新编译。
(3)从ResultSet中遍历结果数据集的时候,存在硬编码,将 获取字段 进行了硬编码,不利于系统维护。
解决方案:将查询的结果集,自动映射成Java对象。
(4)向PrepareStatement中设置参数,对占位符位置和设置参数值,硬编码到Java代码中,不利于系统维护。
解决方案:将SQL语句,已经占位符、参数、全部配置到XML文件中
Myabtis是什么
Mybatis是一个持久层框架
下载地址:https://github.com/mybatis/mybatis-3
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
Mybatis让开发者主要的时间和精力放到SQL上面,通过Mybatis提供的映射,自由灵活(半自动化,大部分SQL自己来实现)满足需要SQL语句
按照面向对象的思想:保存用户数据
User user = New User();
xxx.save(user);
Mybatis框架结构
save怎么实现的,完全可以不关心,User实体和User表建立关系。
Hibernate:完全自动化,不写SQL,完全ORM
Mybatis:半自动化,半ORM,需要考虑save是怎么实现的。
JDBC:完全自己实现。
Mybatis可以将PrepareStatement中输入参数进行输入映射、将查询的结果灵活映射成Java对象(输出映射)
ORM思想
ORM:Object Relational Mapping
让实体和数据库的表建立一对一的关系,实体的属性和表的字段是对应。
建立关系之后,不需要直接操作表,而是操作表对应的实体类对象。
Mybatis框架结构
Mybatis入门使用
项目结构如下:此处项目结构只是为了更好的演使用Mybatis,项目结构不合理
(1)创建Maven工程
详细步骤可以参考:https://blog.csdn.net/h1025372645/article/details/89764478
(2)数据库准备
create database mybatis01;
use mybatis01;
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '下单用户id',
`number` varchar(32) NOT NULL COMMENT '订单号',
`createtime` datetime NOT NULL COMMENT '创建订单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `FK_orders_1` (`user_id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `orders` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);
create table user2(
id varchar(50) primary key not null ,
name varchar(50) not null
);
(3)添加jar包.
<?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.hyx.mybatis</groupId>
<artifactId>learning-mybatis-hyx</artifactId>
<version>1.0-SNAPSHOT</version>
<!--jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<mybatis.version>3.4.4</mybatis.version>
<mysql.version>5.1.34</mysql.version>
<log4j.version>1.2.17</log4j.version>
<fastjson.version>1.2.35</fastjson.version>
<slf4j.version>1.7.25</slf4j.version>
</properties>
<dependencies>
<!-- mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!--mysql包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 日志文件管理包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- 格式化对象,方便输出日志 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--测试包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<!--此处的配置很重要,如果这里不对配置文件进行编译过滤
那么你放到其他文件夹下的配置文件就会丢失
产生异常-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
(4)核心配置文件:sqlMapconfig.xml
配置数据源(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"></transactionManager>
<dataSource type="POOLED">
<!--数据库连接要素,数据库,数据库位置,账户,密码-->
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis01"></property>
<property name="username" value="root"></property>
<property name="password" value="123"></property>
</dataSource>
</environment>
</environments>
</configuration>
(5)建立实体类,与数据库表一一对应
User1自增型主键
package com.hyx.a;
import java.util.Date;
public class User {
private Integer id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public User() {
}
public User(String username, String sex, Date birthday, String address) {
this.username = username;
this.sex = sex;
this.birthday = birthday;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" + "id=" + id + ", username='" + username + '\'' + ", sex='" + sex + '\'' + ", birthday=" + birthday + ", address='" + address + '\'' + '}';
}
}
User2非自增型主键
package com.hyx.a;
public class User2 {
private String id;
private String name;
public User2(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "id: "+id+" name: "+name;
}
}
(6)映射文件:在映射文件中配置SQL语句
命名:
User.xml(原始ibatis命名)
XXXMapper.xml:Mapper代理开发映射文件名
User ->UserMapper
Order->OrderMapper
<?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="test">
<select id="findUserById" parameterType="int" resultType="com.hyx.a.User">
select * from user where id = #{id}
</select>
<!--查询用户列表:非主键查询-->
<select id="findUserByName" parameterType="string" resultType="com.hyx.a.User">
select * from user where username like '%${value}%'
</select>
<!--添加用户-->
<insert id="insertUser" parameterType="com.hyx.a.User">
insert into user(username, birthday, sex, address)
values (#{username}, #{birthday}, #{sex}, #{address})
</insert>
<!--添加用户:返回自增主键
keyProperty:将查询得到的主键设置到parameterType指定对象的那个属性上
order:执行的属性,相对于insert执行顺序来讲,在insert后面
-->
<insert id="insertUser1" parameterType="com.hyx.a.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into user(username, birthday, sex, address)
values (#{username}, #{birthday}, #{sex}, #{address})
</insert>
<!--添加用户:返回非自增主键
执行过程:先通过UUID得到主键,将主键设置到User对象中id属性中。
其次通过insert插入,从User对象获取id属性。
-->
<insert id="insertUser2" parameterType="com.hyx.a.User2">
<selectKey keyProperty="id" resultType="string" order="BEFORE">
select uuid()
</selectKey>
insert into user2(id,name)
values (#{id},#{name})
</insert>
<!--根据主键删除用户-->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>
(7)在核心配置文件加载映射文件
<?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"></transactionManager>
<dataSource type="POOLED">
<!--数据库连接要素,数据库,数据库位置,账户,密码-->
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis01"></property>
<property name="username" value="root"></property>
<property name="password" value="123"></property>
</dataSource>
</environment>
</environments>
<!--配置实体类的xml文件,在这文件中执行sql语句-->
<mappers>
<mapper resource="com/hyx/a/User.xml"></mapper>
<mapper resource="com/hyx/b/User1.xml"></mapper>
</mappers>
</configuration>
(8)配置日志输出文件
# Global logging configuration
#在开发环境下日志级别设置为debug,生产环境下设置成info或error
log4j.rootLogger=debug, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
(9)Java代码实现使用mybatis对数据库进行操作
package com.hyx.a;
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 java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class Demo01 {
/**
* 查询所有
* @throws IOException
*/
@Test
public void fun() throws IOException {
//得到配置文件流
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapconfig.xml");
//通过配置创建会话工厂
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
//通过工厂创建SQLSession会话
SqlSession sqlSession = build.openSession();
//通过SQLSession操作数据库
User user = sqlSession.selectOne( "test.findUserById",1 );
sqlSession.close();
System.out.println(user);
}
/**
* 模糊名字查询
* @throws IOException
*/
@Test
public void fun1() throws IOException {
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream( "sqlMapconfig.xml" );
//通过配置创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build( inputStream );
//通过工厂创建SQLSession会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SQLSession操作数据库
List<User> userList = sqlSession.selectList( "test.findUserByName", "小" );
sqlSession.close();
for (User u:userList) {
System.out.println(u);
}
}
/**
* 向数据库中添加一个对象
* @throws IOException
*/
@Test
public void fun2() throws IOException {
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream( "sqlMapconfig.xml" );
//通过配置创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build( inputStream );
//通过工厂创建SQLSession会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SQLSession操作数据库
User user = new User( "Lw", "男", new Date(), "浙江嘉兴" );
int insert = sqlSession.insert( "test1.insertUser", user );
sqlSession.commit();
sqlSession.close();
System.out.println(user);
}
/**
* 向向数据库添加一个用户,并返回其id
* id为int型
* @throws IOException
*/
@Test
public void fun3() throws IOException {
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream( "sqlMapconfig.xml" );
//通过配置创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build( inputStream );
//通过工厂创建SQLSession会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SQLSession操作数据库
User user = new User( "LL", "1", new Date(), "浙江嘉兴" );
int insert = sqlSession.insert( "test.insertUser1", user );
sqlSession.commit();
sqlSession.close();
System.out.println(user);
}
/**
* 向向数据库添加一个用户,并返回其id
* id为String型
* @throws IOException
*/
@Test
public void fun4() throws IOException {
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream( "sqlMapconfig.xml" );
//通过配置创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build( inputStream );
//通过工厂创建SQLSession会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SQLSession操作数据库
User2 user2 = new User2( "test");
int insert = sqlSession.insert( "test.insertUser2", user2 );
sqlSession.commit();
sqlSession.close();
System.out.println(user2);
}
/**
* 删除一个用户
* @throws IOException
*/
@Test
public void fun5() throws IOException {
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream( "sqlMapconfig.xml" );
//通过配置创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build( inputStream );
//通过工厂创建SQLSession会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SQLSession操作数据库
int delete = sqlSession.delete( "test.deleteUser",30 );
sqlSession.commit();
sqlSession.close();
System.out.println(delete);
}
}
总结
(1)selectOne和selectList区别
selectOne:按照唯一值查询,只有一条结果返回。
selectList:查询结果有多条
(2)#{ }和${}区别
1 #是将传入的值当做字符串的形式,eg:select id,name,age from student where id =#{id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id ='1'.
2 $是将传入的数据直接显示生成sql语句,eg:select id,name,age from student where id =${id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id = 1.
3 使用#可以很大程度上防止sql注入。(语句的拼接)
4 但是如果使用在order by 中就需要使用 $.
5 在大多数情况下还是经常使用#,但在不同情况下必须使用$.