SSM框架
一、mybatis框架
1.介绍
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
半自动的ORM(Object/ Relational Mapping,即对象关系映射)框架。ORM框架常用有两个:Hibernate和MyBatis框架。
2.ORM的介绍
ORM(对象关系映射):以对象的方式操作数据库
比如定义一个对象和数据库表字段一致,那么就可以直接操作这个对象,就可以自动生成SQL语句.
如:userDao.insert(user对象) ,无需书写SQL语句就可以实现数据的插入
ORM的核心映射机制
数据表 <-对应-> java对象
数据表字段 <-对应-> java对象中的属性
1)全自动映射
当用户执行代码userDao.insert(user对象),映射框架解析成insert into 表名(字段1,字段2,字段3...) values(属性值1,属性值2,属性值3.....)
------------------------------------------
用户查询操作:List<User> userList = userDao.selectList(user对象);
select * from 表名 where xxxx=xxxx and xxx= xxx
结果集自动的封装成对象
自动实现对象的封装
自动生成SQL语句
2)半自动ORM的mybatis
可以实现对象的自动封装,但是不能自动生成SQL语句.
3.mybatis的入门代码编辑(Maven项目下)
总体的项目结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDR0Aujp-1659013934685)(D:\Typora\bin\document\img\1658917077363.png)]
1.导入jar包
<dependencies>
<!--导入MySQL的驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!--导入MyBatis的jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
2.数据库表和实体对象
必须保证数据表和对象一一映射,表中字段和对象属性一一映射
3.编写xxxMapper接口
(和Dao接口一类,只是命名格式不同,用来定义操作数据库的方法)
4.编写xxxMapper对应的映射文件xxxMapper.xml
该xml文件只是替代了实现类,在该xml中书写SQL
<?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="xxxMapper的全限定名(全路径)">
<select id="Mapper接口中对应的方法名" resultType="要封装实体的全限定名">
SQL语句
</select>
<inser id=""></inser>
<update id=""></update>
<delete id=""></delete>
</mapper>
----------------------------------------------------------------------------------
<!--
namespace:
1.与mapper的接口文件一一映射 接口的包路径
2.路径内容必须唯一,如果重复mybatis一定报错提示.
-->
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">
<!--
1.根据业务规范,挑选sql标签
1.1 查询: select
1.2 新增: insert
1.3 修改: update
1.4 删除: delete
2.id属性必须与接口中的方法名称一一对应.
3.resultType 只有查询操作有该属性. 内容:实体对象的包路径写法
-->
<select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">
select * from demo_user
</select>
</mapper>
5.核心配置文件mybatis-config.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>
<!--设置连接数据库的环境
数据库可以有多个环境,但一次只能用一个,default="xxx"就是对应的环境,绑定的是对应的id
-->
<environments default="development">
<environment id="development">
<!--事务管理,为默认的jdbc-->
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&rewriteBatchedStatements=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
6.单元测试
步骤:
1.读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
2.通过SqlSessionFactoryBuilder 创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resource);
3.通过SqlSessionFactory获得SqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
4.获取Mapper接口
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
5.调用mapper接口中的方法
List<User> userList = userMapper.getAllUser();
或者使用[了解]
List<User> list = sqlSession.selectList("com.atguigu.mybatis.mapper.UserMapper.getAllUser");
getAllUser()是mapper接口中的方法,mybatis会根据映射关系,执行映射文件中的id为getAllUser的sql标签
@Test
public void findCount() throws IOException {
InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resource);
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
int count = mapper.findCount();
System.out.println(count);
}
userMapper.xxx调用的是接口中的方法,mybatis根据映射关系,执行映射文件中id为xxx的sql标签.
注意:在接收返回数据时,如果根据主键查询必返回一个对象,用对象接收.如果不确定,则使用list<实体对象>进行接收
7.Sqlsession的简化操作
通过@Before标签 简化sqlSession的赋值操作
private SqlSession sqlSession;
@Before
public void init() throws IOException {
//读取mybatis-config.xml核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//创建mybatis中操作数据库的会话对象SqlSession
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
sqlSession = sqlSessionFactory.openSession();
}
@Test
public void findCount() throws IOException {
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
int count = mapper.findCount();
System.out.println(count);
}
4.mybatis常见错误及解决办法
报错说明1:
org.apache.ibatis.binding.BindingException: Type interface com.jt.mapper.UserMapper is not known to the MapperRegistry.
解决方案1:
1.检查namespace命名是否与接口一致
2. 检查Mybatis核心配置文件是否加载映射文件.
报错说明2:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.jt.mapper.UserMapper.findAll
解决方案2:
检查xml映射文件中的ID是否与接口方法一致.
报错说明3:
The error may exist in mybatis/mappers/UserMapper2.xml
解决方案3:
检查mybatis核心文件加载mapper映射文件的路径是否正确.
5.log4j日志的使用
在pom.xml中引入jar包,在resources下放置log4j.xml
需求:在使用mybatis时,执行时不会打印SQL语句,为了检验sql语句的执行正确性,使用log4j用来在执行时打印SQL
位置:在resources下
日志级别
日志级别从左到右打印的内容越来越详细
FATAL(致命) > ERROR(错误) > WARN(警告) > INFO(信息) > DEBUG(调试)
6.数据库的动态配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkwod1Fq-1659013934695)(D:\Typora\bin\document\img\1658922186039.png)]
#key=value
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&rewriteBatchedStatements=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
serverTimezone=UTC 时区:标准时区
rewriteBatchedStatements=true 批处理,提高批量处理SQL语句的执行效率
characterEncoding=utf-8 编码格式utf-8
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
7.mybatis核心配置文件mybatis-config.xml
mybatis-config.xml中,所有的配置都是在标签内,这些标签在使用时,要遵循相应的顺序
properties,settings,typeAliases,
typeHandlers,objectFactory,
objectWrapperFactory,reflectorFactory,plugins,
environments,databaseIdProvider,mappers.
从上到下的顺序
8.mybatis中typeAliases(别名)的使用
需求:在xxxMapper.xml中,resultType=“返回值类型”,书写的太复杂,可以使用别名定义.
<select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">
</select>
此处的User就是一个别名,代表com.atguigu.mybatis.pojo.User
通过下面的别名定义实现
1|2|4 在mybatis-config.xml中配置
3在实体类上
-----------------------------------
<select id="getAllUser" resultType="User">
</select>
1)通过标签定义
<!--定义别名-->
<typeAliases>
<!-- 通过alias指定对象的别名 -->
<typeAlias type="com.atguigu.mybatis.pojo.User" alias="User"/>
</typeAliases>
2)简化alias
<!--定义别名-->
<typeAliases>
<!--如果没有alias属性 则默认使用类名 别名不区分大小写-->
<typeAlias type="com.atguigu.mybatis.pojo.User"/>
</typeAliases>
3)注解写法
@Alias("User")
public class User implements Serializable {...}
4)定义别名
<typeAliases>
<package name="com.atguigu.mybatis.pojo"/>
</typeAliases>
9.映射文件中的元素
映射文件是 MyBatis框架中十分重要的文件,在映射文件中,元素是映射文件的根元素,其他元素都是它的子元素
1、< select >
用于映射查询语句,它用于从数据库中读取出数据,并组装数据给业务开发人员。
<select id="findUserById" parameterType="Integer" resultType="com.ssm.po.User">
select * from t_user where id=#{id}
</select>
上述语句中的唯一标识为findUserById,它接收一个 Integer类型的参数,并返回一个User类型的对象。
2、 < insert >元素< update > < delete >
用于映射插入语句,在执行完元素中定义的SQL语句后,会返回一个表示插入记录数的整数。
<!--//添加用户 -->
<insert id="addUser" parameterType="com.ssm.po.User">
insert into t_user(username,jobs,phone) values(#{username},#{jobs},#{phone})
</insert>
3、 < sql >元素
元素的作用就是定义可重用的SQL代码片段,然后在其他语句中引用这一代码片段。
定义重复SQL:
< sql id=“user_column”>
id,name,age,sex
< /sql>
引入标签:
< include refid=“user_column”/>
<sql id="user_column">
id,name,age,sex
</sql>
<select id="getAllUser" resultType="User">
select <include refid="user_column"/> from demo_user
</select>
10.参数传递
#{}和${}的用法和区别
#号它是有预编译的效果(相当于 PraperStatement ),参数使用?进行占位,并且默认为参数添加引号
$号是直接将字符串进行拼接,没有预编译的效果,使用时需要手动添加引号
原则: 能用#号 不要使用$符,除非以字段名称为参数时使用.
1.单值参数传递
mybatis单值数据传递时和参数的名称无关. 通过参数下标的方式获取的.
建议: 虽然和名称无关,但是一般的参数 见名知意.
<select id="findUserByName" resultType="User">
select * from demo_user where name='${abc}'
</select>
2.多值参数传递
1)通过数组进行取值
Mybatis进行多值参数传递时,内部使用数组的结构,所以需要通过下标的方式取值.
例如: Available parameters are [arg0, arg1, param1, param2]
<select id="findUserByAS" resultType="User">
<!--select * from demo_user where age=#{arg0} and sex=#{arg1}-->
select * from demo_user where age=#{param1} and sex=#{param2}
</select>
弊端: 用户传递的数据是有参数名称的, 如果大量使用下标的方式,则会导致sql业务理解不方便
2)Map集合
说明: 如果用户需要进行多值参数传递,则可以使用map集合进行封装.
编辑测试类:
/**
* 要求 按照age和性别查询数据
*/
@Test
public void test04(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int age = 3030;
String sex = "男";
Map<String,Object> map = new HashMap<>();
map.put("age",age);
map.put("sex",sex);
List<User> list = mapper.findUserByMap(map);
list.forEach(System.out::println);
}
xml映射文件
<!--
如果参数是Map集合,则#{map中的key}
-->
<select id="findUserByMap" resultType="User">
select * from demo_user where age=#{age} and sex=#{sex}
</select>
3)注解封装
说明: 使用@Param注解封装参数
注解封装在底层还是运用了map集合进行的处理
- 编辑测试类
/**
* mybatis 多值查询,注解写法
*/
@Test
public void test05(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int age = 2851;
String sex= "女";
List<User> list = mapper.findUserByAnno(age,sex);
list.forEach(System.out::println);
}
- 编辑接口
/**
* 原理说明:
* Mybatis中使用多值参数传递时,核心用法就是将参数封装为Map集合.
* key: @Param("age") 中的值 age
* value: int age 的值
* 其中的key不能重复. 如果一旦传递map集合则取值时必须使用#{key}
* @param age
* @param sex
* @return
*/
List<User> findUserByAnno(@Param("age") int age,@Param("sex") String sex);
- 编辑映射文件
<select id="findUserByAnno" resultType="User">
select * from demo_user where age=#{age} and sex=#{sex}
</select>
4)实体对象封装
需求: 根据实体对象中的数据查询数据.
- 编辑测试类
/**
* 实体对象查询
* 规则说明: 如果参数较多,则可以使用对象的方式封装.
*/
@Test
public void test06(){
User user = new User();
user.setName("铁扇公主");
user.setAge(1273);
user.setSex("女");
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list = mapper.findUser(user);
list.forEach(System.out::println);
}
- 编辑Mapper接口
List<User> findUser(User user);
- 编辑Mapper.xml映射文件
<!--
如果参数是单值,并且使用对象的方式包装.则取值时和名称无关,和属性有关
前提条件: 对象中必须有get/set方法..
-->
<select id="findUser" resultType="User">
select * from demo_user where name=#{name} and age=#{age} and sex=#{sex}
</select>
重要知识理解:
Mybatis中的参数其实只能允许单值传递(数据可以被封装为单值)
在使用mybatis进行数据库的增删改查时,凡是数据发生改变[如增删改]的都需要加上sqlSession.commit();sqlSession.close()用于事务的提交.
11.转义字符
<!--特殊转义字符
> >
< <
& &
万能转义标签 <![CDATA[ 需要转义的内容 ]]>
-->
select * from demo_user where age >=#{starAge} and age <= #{endAge}
------------------------------------------
select * from demo_user where age >=? and age <= ?
lombok的注解说明:
@Accessors(chain = true)
@Accessors 注解用来配置lombok如何产生和显示get和set的方法,@Accessors(chain = true)加上参数以后就可以开启链式编程.
传统set方法赋值(臃肿、占空间)
Person person = new Person();
person.setName("wang");
person.setSex("男");
person.setEmail("123@qq.com");
person.setDate(new Date());
person.setAddr("山东");
加上@Accessors(chain = true)
Person person = new Person();
person.setName("wang").setSex("男").setEmail("123@qq.com").setDate(new Date()).setAddr("山东");
11.ResultMap
当表中的字段与POJO中的属性不能完全匹配时, 则需要使用resultMap映射.
ResultMap解决在数据库中的字段名和实体类中属性名不一致,无法自动映射的问题(数据库:user_id 属性:userId)
案例描述
1)实体类:
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class Users implements Serializable {
private Integer id;
private String tName;
private Integer tAge;
private String sex;
}
2)UsersMapper接口
public interface UserMappers {
List<Users> selectUser();
}
3)UsersMapper.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.ssm.mybatis.mapper.UserMappers">
<!--
解决的数据库字段和实体类属性因为不同而无法自动映射的问题
autoMapping: 如果字段与名称相同,是否自动映射, 默认值为true 旧版本为false
id: resultMap的主键标识 可以复用
result:除id外使用
column="数据库字段"
property="对应的属性"
-->
<resultMap id="userIds" type="users" autoMapping="false">
<result column="t_name" property="tName"/>
<result column="t_age" property="tAge" />
</resultMap>
<select id="selectUser" resultType="users">
select * from demo_user1
</select>
</mapper>
4)mybatis-config.xml
在properties标签下生效,要依照执行顺序
<settings>
<!--是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
........................................
<mappers>
<mapper resource="mappers/UserMappers.xml"/>
</mappers>
5)测试类
@Test
public void selectUser() throws IOException {
InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(rs);
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMappers mapper=sqlSession.getMapper(UserMappers.class);
List<Users> userList=mapper.selectUser();
System.out.println(userList);
}