MyBatis02
1.封装MyBatis工具类
泛型:避免类型的转换,性能高
ThreadLocal:线程副本、线程变量 当前线程作为key,每个线程都有自己的对象
内存泄漏(为什么、怎么解决)
参考:MybatisUtil
public class MybatisUtil {
private static SqlSessionFactory factory;
private static ThreadLocal<SqlSession> local;//线程副本或线程变量 等价于 Map<Thread,Object>,key当前线程 避免线程安全
static {
try {
//1.加载配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2.获取会话工厂对象 2种设计模式:1.工厂模式 2.建造者模式
factory= new SqlSessionFactoryBuilder().build(is);
local=new ThreadLocal<>();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @description:获取会话,每个线程都有自己的会话对象
* @return: 会话对象
*/
public static SqlSession getSqlSession(){
SqlSession sqlSession=local.get();
if(sqlSession==null){
sqlSession=factory.openSession();
local.set(sqlSession);
}
return sqlSession;
}
/**
* @description: 返回持久层接口的实现类
* @param clz 持久层接口对应的Class对象
* @return:
*/
public static <T> T getMapper(Class<T> clz){
return local.get().getMapper(clz);
}
/**
* @description: 回收对象
* @return:
*/
public static void close(){
local.get().close();
local.remove();//删除,防止内存泄漏
}
}
2.数据库连接池
池化技术:有效控制连接,让资源得到充分的使用
常用池化:1.数据库连接池 2.线程池 3.Redis连接池 等等
目的:1.有效控制最大连接,防止服务器宕机 2.充分使用每个连接对象
数据库连接池:有效控制数据库的连接对象,可以让连接更充分的使用
目前市场上数据库连接池:Druid(阿里巴巴)
使用步骤:
1.依赖jar
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
</dependencies>
编写数据库连接类
继承:PooledDataSourceFactory
public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
//替换数据库连接池为Druid的连接池
public MyDruidDataSourceFactory(){
this.dataSource=new DruidDataSource();
}
}
3.实现配置
需要替换成自定义连接池
<dataSource type="com.feri.mybatis.config.MyDruidDataSourceFactory">
<!--使用$ + 占位符-->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
3.ResultType和ResultMap
resultType:用在查询标签上,实现查询语句的的结果行的数据类型
要求:类的属性名必须和数据库表的字段名一模一样
适用于简单的映射
resultMap:用来定义数据库的字段和类的标的属性的对应关系,先定义,再使用
好处:
1.解决类的属性名和查询字段不一致的情况
2.实现多表关系映射查询
4.多表关系
关系型数据库:Mysql、Postgresql、Oracle
哪些关系?
一对一:用户表--用户详情表
一对多:老师表--学生表
多对一:学生表--老师表
多对多:商品表--订单表 中间表:订单详细表 2张表如果相互存在一对多,那么就是多对多。必须有中间表
E-R图:实体关系映射图
充分描述或展示表与表之间的关系
Mybatis实现多表关系,就很简单。
只有2种情况:
1.对象
A和B
A-1-1-B 一对一
A-N-1-B 多对一
A中就有B的对象
借助中的
2.集合
A和B
A-1-N-B 一对多
多对多在真实情况下,就是2个一对多
A中就有B的集合
借助中的
实现一对一
association+javaType
1.编写实体类
2.编写持久层接口
3.编写持久层映射文件
4.运行测试
实现一对多
一对多:用户表----手机表
collection+ofType
1.编写实体类
2.编写持久层接口
3.编写持久层映射文件
4.运行测试
<mapper namespace="com.qfedu.mapper.UserMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into t_user (phone,username,password)values(#{phone},#{username},#{password})
</insert>
<resultMap id="userMap" type="com.qfedu.pojo.User">
<id property="id" column="id"/>
<result property="phone" column="phone"></result>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<association property="detail" javaType="com.qfedu.pojo.UserDetail">
<id property="id" column="udid"/>
<result property="name" column="uname"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<result property="uid" column="uid"/>
</association>
</resultMap>
<select id="selectById" resultMap="userMap">
select u.*,ud.id udid,ud.uname,ud.sex,ud.address from t_user u inner join t_userdetail ud on u.id=ud.uid where u.id=#{id}
</select>
<resultMap id="userCar" type="com.qfedu.pojo.User">
<id property="id" column="id"/>
<result property="phone" column="phone"></result>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<collection property="cars" ofType="com.qfedu.pojo.Car">
<id property="id" column="cid"/>
<result property="brand" column="brand"></result>
<result property="title" column="title"></result>
<result property="uid" column="uid"></result>
</collection>
</resultMap>
<select id="selectUserCar" resultMap="userCar">
select u.*,c.id cid,c.uid,c.brand,c.title from t_user u inner join t_car c on u.id=c.uid
</select>
</mapper>
5动态sql
就是一些标签,需要死记硬背
动态SQL:可以动态的拼接SQL语句,实现sql复用,简化操作
语法规则:记住以下标签:
sql>:封装可以复用的sql语句,通过
where>:实现where关键字,如果内部为空,则Where关键字不出现,如果内部有内容,则添加Where
trim>:去除
set>:修改 可以去除多余的连接符
if>:分支语句判断 test属性
foreach>:循环,重复操作,可以设置间隔符
Mybatis如何实现批处理?批量新增、批量修改、批量删除
<sql id="s1">
select * from t_car
</sql>
<select id="selectCar" resultType="com.qfedu.pojo.Car">
<include refid="s1"></include>
<where>
<if test="brand !=null">
and brand = #{brand}
</if>
<if test="title != null">
and title = #{title}
</if>
</where>
</select>
</insert>
<insert id="batchAdd" parameterType="list">
insert into t_car (uid,brand,title) values
<foreach collection="list" item="c" separator=",">
(#{c.uid},#{c.brand},#{c.title})
</foreach>
</insert>
<delete id="deleteCarById" >
delete from t_car where id in
<foreach collection="list" open="(" separator="," close=")" item="id" >
#{id}
</foreach>
</delete>
6Lombok
Lombok:是一个开源的小框架,基于注解实现类的getter、setter、构造、toString等方法
目的简化类中的内容,避免重复搬砖
这个框架还有配套的一个Idea插件
使用步骤:
1.安装插件
lombok---install--重启Idea
2.项目中依赖jar
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
3.实体类使用注解,简化代码
@Data //自动实现属性的getter和setter,并重写toString方法
@NoArgsConstructor //无参构造函数
public class User {
private Integer id ;
/** 手机号 */
private String phone ;
/** 密码 */
private String pass ;
/** 时间 */
private Date ctime ;
//对应的详情信息
private UserDetail detail;
public User(String phone, String pass) {
this.phone = phone;
this.pass = pass;
}
}