①. JDBC的缺点(了解)
- ①. 原始jdbc操作(查询数据)
- ②. 原始jdbc操作(插入数据)
- 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能
- sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql 变动需要改变java代码
- 查询操作时,需要手动将结果集中的数据手动封装到实体中。插入操作时,需要手动将实体的数据设置到sql语句的占位符位置
- 使用数据库连接池初始化连接资源
- 将sql语句抽取到xml配置文件中
- 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射
②. Mybatis概述及优缺点
- 与JDBC相比,减少了50%的代码量
- SQL代码从程序中彻底分离出来,可以分离
- 提供XML标签,支持写动态SQL
- 提供映射标签,支持对象与数据库的ORM字段关系映射
- SQL语句编写工作量大,熟练度很高
- 数据库移植性比较差,如果切换数据库的话,SQL语句会有很大的差异
- 读取MyBatis配置文件mybatis-config.xml。mybatis-config.xml作为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接
- 加载映射文件Mapper.xml。Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,个配置文件对应数据库中的一张表
- 创建会话工厂,通过MyBatis的环境等配置信息构造会话工厂SqlSessionFactory
- 创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有方法
- MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的形参的所有方法
- 在Execuotor接口的执行方法中,包含了一个MappedStatement类型的参数,该参数是对映射信息
的封装,用来存储要映射的SQL语句的id、参数等。Mapper.xml文件中的一个SQL对应一个 MappedStatement对象,SQL的id是MappedStatement的id - 输入参数映射。在执行方法时,MapperStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List、基本数据类型和POJO类型),Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对PreparedStatement对象设置参数的过程
- 输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO类型),Executor执行器会通MappedSt atement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程
③. 快速搭建Mybatis工程
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
<scope>runtime</scope>
</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.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.12</version>
</dependency>
- ③. 通过官网写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="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/xiaozhi/mapper/UserMapper.xml"/>
</mappers>
</configuration>
@Data
@ToString
public class User {
private Integer id;
private String userName;
}
<?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.xiaozhi.dao.UserMapper">
<select id="findEmpById" resultType="com.xiaozhi.entity.User" parameterType="Integer">
select * from user where id=#{id};
</select>
</mapper>
public class EmpTest {
@Test
public void test1()throws Exception{
InputStream inputStream= Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
User emp =sqlSession.selectOne("com.xiaozhi.dao.UserMapper.findEmpById",1);
System.out.println(emp);
sqlSession.close();
}
}
- ⑥. 加入日志文件,可以看到打印的SQL log4j.properties
# log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout
④. MyBatis的增删改查操作
public class MybatisUtils {
private MybatisUtils(){}
private static SqlSessionFactory sqlSessionFactory;
static {
try {
InputStream inputStream= Resources.getResourceAsStream("sqlMapConfig.xml");
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
- ②. 查询(查询所有、通过id进行查询、模糊查询)
<?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.xiaozhi.dao.UserMapper">
<select id="findAll" resultType="com.xiaozhi.entity.User">
select * from user
</select>
<select id="findUserById" parameterType="Integer" resultType="com.xiaozhi.entity.User">
select * from user where id=#{id}
</select>
<select id="findUserByName" parameterType="String" resultType="com.xiaozhi.entity.User">
select * from user where username like concat('%',#{value},'%')
</select>
</mapper>
@Test
public void SelectAll()throws Exception{
InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
List<User> list=sqlSession.selectList("userMapper.findAll");
System.out.println(list);
sqlSession.close();
}
@Test
public void selectById()throws Exception{
InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user=sqlSession.selectOne("userMapper.findUserById",1);
System.out.println(user);
sqlSession.close();
}
@Test
public void selectByName()throws Exception{
SqlSession sqlSession = MybatisUtils.getSqlSession();
List<User> list = sqlSession.selectList("userMapper.findUserByName", "x");
System.out.println(list);
}
- ③. 添加一个用户
#{id}:从输入user对象中获取id属性值
<insert id="insertUser" parameterType="com.xiaozhi.entity.User">
insert into user(id,username)values(#{id},#{username})
</insert>
@Test
public void add()throws Exception{
SqlSession sqlSession = MybatisUtils.getSqlSession();
User user=new User();
user.setId(2);
user.setUsername("xiaozhi");
int row=sqlSession.insert("userMapper.insertUser",user);
System.out.println(row);
sqlSession.commit();
sqlSession.close();
}
<update id="updateUser" parameterType="com.itheima.domain.User">
update user set username=#{username},password=#{password} where id=#{id}
</update>
@Test
public void update()throws Exception{
SqlSession sqlSession = MybatisUtils.getSqlSession();
User user=new User();
user.setId(2);
user.setUsername("xiaoxing");
int result=sqlSession.update("userMapper.updateUser",user);
System.out.println(result);
sqlSession.commit();
sqlSession.close();
}
<delete id="deleteById" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
@Test
public void delete()throws Exception{
SqlSession sqlSession = MybatisUtils.getSqlSession();
int result=sqlSession.delete("userMapper.deleteById",1);
System.out.println(result);
sqlSession.commit();
sqlSession.close();
}
⑤. 映射文件总结
-
①. namespace命名空间:作用就是对sql进行分类化管理,理解sql隔离。通常会设置成包名+sql映射文件名注意:使用namespace代理方式开发,namespace有特殊的作用 -
②. 通过select执行数据查询<select id="" parameterType="" resultType="">
- id:标识映射文件的sql,称为statement的id
(将sql语句封装mappedStatement对象中,所以将id称为statement的id ) - #{}:表示占位符,相当于?
- #{id}:其中的id表示接收输入的参数,参数名称是id,如果输入参数是简单类型,#{}中的参数名可以任意,可以value或其他名称
- parameterType:指定输入参数类型,这里指定int型
- resultType:指定sql输出结果的映射的java类型,resultType表示将单条记录映射成的java对象
<mapper namespace="test">
<select id="findCustomerById" parameterType="Integer"
resultType="com.itcast.mybatis.po.User">
select * from user where id = #{id}
</select>
</mapper>
- ③. parameterType 和 resultType
- parameterType:在映射文件中通过parameterType指定输入参数的类型
- resultType:在映射文件中通过resultType指定输出结果的类型
- ④. selectOne(statement,parament)和selectList(statement,parament)
- 第一个参数statement:映射文件中statement的id,等于=namaspace+statementId
- 第二个参数parament:指定和映射文件中所匹配paramtype类型的参数(输入参数)
- session.selectOne 结果是与映射文件中所匹配的resultType类型的对象
- selectOne:表示查询出一条记录进行映射。如果使用了selectOne可以实现,那么使用selectLis也可以实现 (List中只有一个对象)
- selectList:表示查询出一个列表(多个列表)进行映射,如果使用了,如果使用selectList要查询多天记录,不能使用selectOne
1.select * from user where username like ‘%${value}%’
2.select * from user where username like concat('%',
#{}:
1. #{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo等
2. 如果接受简单类型,#{}里面的可以写成value或其他的
3. #{}接受的是pojo。要通过user.user.username的形式获取
${}:
1.表示一个拼接符号,会引起sql注入,所以不建议使用
2.${} 接受输入参数,类型可以是简单类型,pojo等
3.${} 接受的是pojo。要通过 user.user.username的形式获取
select * from user where name =
select * from user where name = ?;
select * from user where name =
select * from user where name = yuze;
|