常用框架SSM:
Spring:它是整合其他框架的框架,核心是IOC和AOP,由20多个模块构成
SpringMVC:它是Spring家族的一个,专门优化控制器(Servlet),提供极简数据提交,数据携带,页面跳转功能
Mybatis:是持久化层的一个框架,用来进行数据库访问的优化,对数据访问层的优化,专注于sql语句,极简化JDBC的访问
三层架构,在项目开发中遵守的一种形式模式:
1.界面层:用来接受客户端的输入,调用业务逻辑层进行功能处理,返回结果给客户端,servlet就是界面层的功能
2.业务逻辑层:用来进行整个项目的业务逻辑处理,向上为界面层提供处理结果,向下问数据访问层要数据
3.数据访问层:用来进行数据库的增删改查操作,向上为业务逻辑层提供数据 界面层---->业务逻辑层---->数据访问层
添加Mybatis依赖和mysql驱动依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
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>
<!-- 读取属性文件jdbc.properties
属性:resource:从resource目录下找指定名称的文件加载
url:使用绝对路径找到文件
-->
<properties resource="jdbc.properties"></properties>
<!-- 配置数据库的环境变量(数据库连接配置)
default:使用下面的environment标签的id属性进行切换配置
id属性就是提供给environment的default属性使用
transactionManager:配置事务管理器
type:指定事务管理的方式
JDBC:事务的控制交给程序员处理
MANAGED:由容器Spring来管理事务
dataSource:配置数据源
JNDI:java命名目录接口,在服务器端进行数据库连接池的管理
POOLED:使用数据库连接池
UNPOOLED:不使用数据库连接池
-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 注册mapper.xml文件
resource:从resource目录下找指定名称的文件注册
url:使用绝对路径找到文件注册
class:动态代理方式下的注册
package:包名注册
-->
<mappers>
<mapper resource="StudentMapper.xml"></mapper>
</mappers>
</configuration>
StudentMapper.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:是整个文件的大标签,用来开始和结束xml文件
namepace:指定命名空间(相当于包名,用来区别不同mapper.xml文件中相同的id属性)
resultType:指定查询返回的结果集的类型,如果是集合,必须是泛型的类型
parameterType:如果有参数,则通过它来指定参数的类型
-->
<mapper namespace="lv">
<select id="getAll" resultType="com.lv.pojo.Student">
select id,name,email,age from student;
</select>
</mapper>
Mybatis对象分析
1.Resources类
解析SqlMapConfig.xml文件,创建出相应对象 InputStream in = Resources.getResourceAsStream(“SqlMapConfig.xml”);2.SqlSessionFactory接口
DefaultSqlSessionFactory是实现类
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);3.SqlSession接口
DefaultSqlSession实现类
为实体类注册别名
1.单个注册
<typeAliases>
<typeAlias type="com.lv.pojo.Student" alias="student"></typeAlias>
</typeAliases>
2.批量注册
<typeAliases>
<package name="com.lv.pojo"/>
</typeAliases>
设置日志输出
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
动态代理的实现规范
1.UsersMapper.xml文件与UsersMapper.java的接口必须同一个目录下
2.UsersMapper.xml文件与UsersMapper.java的接口文件名必须一致,后缀不管
3.UserMapper.xml文件中标签的id值与UserMapper.java的接口中方法名称完全一致
4.UserMapper.xml文件中标签的ParameterType值与UserMapper.java的接口中方法的参数类型完全一致
5.UserMapper.xml文件中标签的resultType值与UserMapper.java的接口中方法的返回值完全一致
6.UserMapper.xml文件中namespace属性必须是接口的完全限定名称
7.在SqlMapConfig.xml文件中注册mapper文件时,使用class = 接口的完全限定名称
动态代理访问的步骤
1.建表User
2.新建maven工程,刷新可视化
3.修改目录
4.修改pom.xml,添加依赖
5.添加jdbc.propertis文件
6.添加SqlMapConfig.xml文件
7.添加实体类
8.添加mapper文件夹,新建UsersMapper接口
9.在mapper文件夹下,新建UsersMapper.xml文件,完成增删改查
10.添加测试类,测试功能
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>
<!--读取属性文件jdbc.properties-->
<properties resource="jdbc.properties"></properties>
<!--设置日志输出-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--实体类注册别名-->
<typeAliases>
<package name="com.lv.pojo"/>
</typeAliases>
<!--配置数据库的环境变量(数据库连接配置)-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<mappers>
<!--<mapper class="com.lv.mapper.UsersMapper"></mapper>-->
<!--批量注册-->
<package name="com.lv.mapper"/>
</mappers>
</configuration>
UsersMapper接口写法:
public interface UsersMapper {
//查询所有的信息的方法
List<User> getAll();
//根据id查询信息的方法
User getId(Integer num);
//模糊查询方法
List<User> getByName(String name);
//更新用户方法
int update(User user);
//增加用户
int insert(User user);
//根据主键删除用户
int delete(Integer id);
//模糊用户名和地址查询
List<User> getByNameorAddress(@Param("columnName") String columnName, @Param("columnValue") String columnValue);
}
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.lv.mapper.UsersMapper">
<select id="getAll" resultType="user">
select id,username,birthday,sex,address from users
</select>
<select id="getId" resultType="user" parameterType="int">
select id,username,birthday,sex,address from users where id = #{id}
</select>
<select id="getByName" resultType="user" parameterType="string">
select id,username,birthday,sex,address from users where username like concat('%',#{name},'%')
</select>
<update id="update" parameterType="user">
update users set username=#{userName},birthday=#{birthday},sex=#{sex},address=#{address}
where id =#{id}
</update>
<insert id="insert" parameterType="user">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into users (username,birthday,sex,address) value (#{userName},#{birthday},#{sex},#{address})
</insert>
<delete id="delete" parameterType="int" >
delete from users where id = #{id}
</delete>
<select id="getByNameorAddress" resultType="user">
select id,username,birthday,sex,address from users where ${columnName} like concat('%',#{columnValue},'%')
</select>
</mapper>
测试类写法:
public class MyTest {
//SqlSession对象
SqlSession sqlSession;
//动态代理对象
UsersMapper uMapper;
//日期的格式化刷子
SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");
@Before
public void open() throws IOException {
//使用文件流读取核心配置文件SqlMapConfig.xml
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//取出sqlSession的对象
sqlSession = factory.openSession();
//取出动态代理对象,完成接口中方法的调用,实则是调用xml文件中相同的标签的功能
uMapper = sqlSession.getMapper(UsersMapper.class);
}
@After
public void close(){
//关闭SqlSession对象
sqlSession.close();
}
@Test
//查询所有的信息
public void testGetAll(){
List<User> list = uMapper.getAll();
list.forEach(user -> System.out.println(user));
}
@Test
//按id查询信息
public void testGetId(){
User u = uMapper.getId(7);
System.out.println(u);
}
@Test
//模糊查询
public void testGetByName(){
List<User> list = uMapper.getByName("小");
list.forEach(users -> System.out.println(users));
}
@Test
//更新数据
public void testUpdate() throws ParseException {
User u = new User(7,"老七",date.parse("1999-07-10"),"2","湖南");
int num = uMapper.update(u);
System.out.println(num);
sqlSession.commit();
}
@Test
//插入数据
public void testInsert() throws ParseException{
User u = new User("老八",date.parse("1999-07-10"),"2","湖南省");
int num = uMapper.insert(u);
System.out.println(num);
sqlSession.commit();
System.out.println(u);
}
@Test
//根据id删除数据
public void testDelete(){
int num = uMapper.delete(32);
System.out.println(num);
sqlSession.commit();
}
@Test
//根据名字和地址模糊查询
public void testgetByNameorAddress(){
List<User> list = uMapper.getByNameorAddress("username","小");
List<User> list2 = uMapper.getByNameorAddress("address","湖");
list.forEach(users -> System.out.println(users));
list2.forEach(users -> System.out.println(users));
}
@Test
//生成uid
public void testUUID(){
UUID uid = UUID.randomUUID();
//replace替换-为空,substring截取16位
System.out.println(uid.toString().replace("-","").substring(16));
}
}
#{}占位符
传参大部分使用#{}传参,底层使用的事preparedStatement对象,是安全的数据访问,防止sql注入
1.如果parameterType的类型是8种基本封装类型+String,则#{}里随便写
2.如果parameterType的类型是实体类的类型,则#{}只能是类中成员变量的名称,而且区分大小写${}字符串拼接或字符串替换(很少用) 字符串拼接,一般用于模糊查询,少用,有sql注入的风险 1.如果parameterType的类型是8种基本封装类型+String,则${}里随便写,如果是3.5.1以下版本只能写value 2.如果parameterType的类型是实体类的类型,${}只能是类中成员变量的名称. 3.concat('%',#{name},'%') 以后用这种做模糊查询 字符串替换: 需求:模糊地址或模糊用户名查询 <select id="getByNameorAddress" resultType="user"> select id,username,birthday,sex,address from users where ${columnName} like concat('%',#{columnValue},'%') </select>
返回主键值:
在插入语句结束后,返回自增的主键值到入参的id属性中
keyProperty:user对象的哪个属性来传入返回值
resultType:返回主键的类型
order:在插入语句执行前还是后返回主键的值
<insert id="insert" parameterType="user">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into users (username,birthday,sex,address) value (#{userName},#{birthday},#{sex},#{address})
</insert>
UUID:
全球唯一字符串,由36个字母数字中划线组成
UUID uid = UUID.randomUUID();
//replace替换-为空,substring截取16位
System.out.println(uid.toString().replace("-","").substring(16));
动态sql:
可以定义代码片段,可以进行逻辑判断,可以进行循环处理,(批量处理),使条件判断更为简单
<sql>:用来定义代码片段,可以将所有的列名,或复杂的条件定义为代码片段,供使用时调用
<include>:用来引用<sql>定义的代码片段
<if>:进行条件判断
<where>:进行多条件拼接,在查询,删除,更新中使用
<set>:有选择的进行更新处理,至少更新一列
<foreach>:用来进行循环遍历,完成循环条件查询,批量删除,批量增加,批量更新
collection:用来指定入参的类型,list,map,array
item:每次循环遍历出来的值或对象
separator:多个值之间的分隔符
open:循环外的前括号
close:循环外的后括号
用动态sql代码简化的UsersMapper.xml:
<select id="getByCondition" parameterType="user" resultType="user">
select <include refid="allColumns"></include>
from users
<where>
<if test="userName != null and userName != ''">
and username like concat('%',#{userName},'%')
</if>
<if test="birthday != null">
and birthday = #{birthday}
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
<if test="address != null and address != ''">
and address like concat('%',#{address},'%')
</if>
</where>
</select>
<update id="updateset" parameterType="user">
update users
<set>
<if test="userName != null and userName !=''">
username = #{userName},
</if>
<if test="birthday != null">
birthday = #{birthday},
</if>
<if test="sex != null and sex != ''">
sex = #{sex},
</if>
<if test="address != null and address != ''">
address = #{address}
</if>
</set>
where id = #{id}
</update>
<select id="getByIds" resultType="user">
select <include refid="allColumns"></include>
from users
where id in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
<delete id="deleteBatch">
delete from users where id in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
<insert id="insertmore">
insert into users (username,birthday,sex,address) values
<foreach collection="list" item="user" separator=",">
(#{user.userName},#{user.birthday},#{user.sex},#{user.address})
</foreach>
</insert>
//多个update操作JDBCurl要加这段&allowMultiQueries=true
<update id="updatemore" parameterType="user">
<foreach collection="list" item="u" separator=";">
update users
<set>
<if test="u.userName != null and u.userName !=''">
username = #{u.userName},
</if>
<if test="u.birthday != null">
birthday = #{u.birthday},
</if>
<if test="u.sex != null and u.sex != ''">
sex = #{u.sex},
</if>
<if test="u.address != null and u.address != ''">
address = #{u.address}
</if>
</set>
where id = #{u.id}
</foreach>
</update>
指定参数位置:
如果入参是多个,可以通过指定参数位置进行传参,是实体包含不住的条件,实体类只能封装成员变量的条件
如果某个成员变量要有区间范围的判断,或者有两个值进行处理,则实体类包不住
<select id="getByBirthday" resultType="user">
select <include refid="allColumns"></include> from users
where birthday between #{arg0} and #{arg1}
</select>
入参是map:(重点)
如果入参超过一个以上,使用map封装查询条件,查询条件更明确
<select id="getByMap" resultType="user">
select <include refid="allColumns"></include> from users
where birthday between #{Begin} and #{End}
</select>
返回值是map:
<select id="getMap" resultType="map" parameterType="int">
select username,address from users where id = #{id}
</select>
resultMap简单用法:
<resultMap id="bookmap" type="book">
//主键绑定
<id property="id" column="bookid"></id>
//非主键绑定
<result property="name" column="bookname"></result>
</resultMap>
表之间的关联关系:
无论是什么关联关系,如果某方持有另一方集合,使用<collection>,如果是对象,使用<association>
1.一对多:客户和订单就是典型的一对多关联关系,一个客户可以有多个订单
使用一对多的关联关系,可以满足查询客户的同时查询该客户名下的订单
<select id="getById" parameterType="int" resultMap="customermap">
select c.id cid,name,age,o.id oid,orderNumber,orderPrice,customer_id
from customer c left join orders o on c.id = o.customer_id
where c.id=#{id}
</select>
2.多对一:订单和客户就是多对一关联,站在订单的方向查询订单的同时将客户信息查出
<select id="getById" parameterType="int" resultMap="ordersmap">
select o.id oid,orderNumber,orderPrice,customer_id,c.id cid,name,age
from orders o inner join customer c on o.customer_id = c.id
where o.id=#{id}
</select>
3.一对一
4.多对多
事务:
多个操作同时完成,或同时失败称为事务处理
四个特性:一致性,持久性,原子性,隔离性
Mybatis框架中设置事务
<transactionManager type="JDBC"></transactionManager>
设置自动提交
sqlSession = factory.openSession(true);
缓存:
Mybatis框架提供两级缓存,一级缓存和二级缓存,默认开启一级缓存
缓存为了提交查询效率
一级缓存用的是sqlSession的作用域,同一个sqlSession共享一级缓存的数据
二级缓存用的事mapper的作用域,不同的sqlsession只要访问的同一个mapper.xml文件,则共享二级缓存
ORM:
ORM(Object Relational Mapping):对象关系映射
Mybatis框架是ORM非常优秀的框架
java语言中以对象的方式操作数据,存到数据库中以表的方式进行存储,对象中的成员变量与表中
的列之间的数据互换成为映射