mybatis
2021-04-21 14:31:31 0 举报
AI智能生成
mybatis总结
作者其他创作
大纲/内容
三层架构<br>
持久层(DAL)
和数据库进行交互<br>
业务层(BLL)
处理业务需求
表现层(UI)
页面展示数据,jsp,html等<br>
ORM<br>
对象-关系数据库映射 Object-Relation Mapping<br>ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中<br>
MVC
Model(模型)
一般指业务模型,代码中指JavaBean部分,数据模型 entity 业务模型 service
View (视图)
一般指用户看到的界面<br>,代码中指jsp,html,servlet等
Controller(控制器)
处理用户的请求和响应给用户的逻辑业务需求,对应代码中的servlet部分
JDBC步骤<br>
<br>1,使用jdbc编程需要连接数据库,注册驱动和数据库信息<br>2,操作Connection,打开Statement对象<br>3,通过Statement对象执行SQL,返回结果到ResultSet对象<br>4,使用ResultSet读取数据,然后通过代码转化为具体的POJO对象<br>5,关闭数据库相关的资源
jdbc技术列举
原生JDBC<br>
Spring的JdbcTemplate(只属于工具)
Apache的DBUtils(只属于工具)
JDBC的缺点和Mybatis的优点
JDBC缺点
(1)需要频繁的创建数据库连接<br>(2)涉及到的增删改查等功能需要在各个java文件中编写大量代码<br>(3)对于底层事务、数据类型转换等都需要手动处理,又是各种代码<br>
mybatis优点
(1)封装了jdbc对数据库的各种操作,减少代码<br>(2)增加了连接池、一、二级缓存<br>(3)可以自动生成sql语句
什么是mybatis<br>
MyBatis是一款优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。
mybatis和hibernate比较
1. Hibernate是全自动的,MyBatis是半自动的 Hibernate实现了部分自动生成SQL<br>2. MyBatis真正实现了java代码和sql的分离<br>3. SQL优化上 MyBatis强于Hibernate<br>4. MyBatis优化维护方便 SQL全存在于XML中 不需要修改源代码<br>5. 开发效率上 Hibernate略强于mybatiss<br>6. 从性能上说 因为Mybatis全都是自己手写的SQL,因此性能相对较高反之。Hibernate更加提倡使用HQL,HQL往往会查询更多的字段,从而性能反而较低
环境搭建(非注解)
第一步:创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?><br><project xmlns="http://maven.apache.org/POM/4.0.0"<br> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><br> <modelVersion>4.0.0</modelVersion><br><br> <groupId>com.wuyang</groupId><br> <artifactId>ssm_mybatis</artifactId><br> <version>1.0-SNAPSHOT</version><br> <packaging>jar</packaging><br><br> <dependencies><br> <!--mybatis依赖--><br> <dependency><br> <groupId>org.mybatis</groupId><br> <artifactId>mybatis</artifactId><br> <version>3.5.6</version><br> </dependency><br> <!--mysql数据库依赖--><br> <dependency><br> <groupId>mysql</groupId><br> <artifactId>mysql-connector-java</artifactId><br> <version>5.1.49</version><br> </dependency><br> <!--日志依赖--><br> <dependency><br> <groupId>log4j</groupId><br> <artifactId>log4j</artifactId><br> <version>1.2.12</version><br> </dependency><br> <!--测试依赖--><br> <dependency><br> <groupId>junit</groupId><br> <artifactId>junit</artifactId><br> <version>4.11</version><br> </dependency><br> </dependencies><br><br></project>
第二步:创建实体类和dao的接口
实体类
public class User implements Serializable {<br>private Integer id;<br>private String username;<br>private String address;<br>private String sex;<br>private Date birthday;<br><br>get set<br>tostring<br>实现Serializable 接口是为了确保类的唯一性,会自动分配一个类的id,确保序列化的执行<br>
接口
/**<br> * 用户持久层接口<br> */<br>public interface UserDao {<br><br> /**<br> * 查询所有<br> * @return<br> */<br> List<User> findAll();<br>}
第三步:创建Mybatis的主配置文件
<?xml version="1.0" encoding="UTF-8" ?><br><!DOCTYPE configuration<br> PUBLIC "-//mybatis.org//DTD Config 3.0//EN"<br> "http://mybatis.org/dtd/mybatis-3-config.dtd"><br><!--mybatis主配置文件--><br><configuration><br> <!--mybatis全局设置--><br> <settings><br> <!--控制日志输出到控制台--><br> <setting name="logImpl" value="STDOUT_LOGGING"/><br> </settings><br> <!--配置环境--><br> <environments default="mysql"><br> <!--配置mysql环境--><br> <environment id="mysql"><br> <!--配置事务--><br> <transactionManager type="JDBC"/><br> <!--配置数据源(连接池)--><br> <dataSource type="POOLED"><br> <!--配置数据库的4个基本信息--><br> <property name="driver" value="com.mysql.jdbc.Driver"/><br> <property name="url" value="jdbc:mysql://localhost:3306/ssm"/><br> <property name="username" value="root"/><br> <property name="password" value="147"/><br> </dataSource><br> </environment><br> </environments><br> <!--配置映射文件--><br> <mappers><br> <mapper resource="com/wuyang/dao/UserDao.xml"/><br> </mappers><br></configuration><br>
第四步:创建映射配置文件
<?xml version="1.0" encoding="UTF-8" ?><br><!DOCTYPE mapper<br> PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"<br> "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><br><mapper namespace="com.wuyang.dao.UserDao"><br> <!--配置查询所有,id对应UserDao接口中方法findAll()--><br> <select id="findAll" resultType="com.wuyang.entity.User"><br> select * from user;<br> </select><br></mapper>
第五步,创建测试类
初始化
@Before//用于测试方法执行之前执行<br> public void init() throws Exception {<br> //读取配置文件<br> in = Resources.getResourceAsStream("sqlMapConfig.xml");<br> //创建SqlSessionFactory工厂<br> SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);<br> //使用工厂生产SqlSession对象,true是自动提交事务<br> sqlSession = factory.openSession(true);<br> //使用SqlSession创建Dao接口的代理对象<br> userDao = sqlSession.getMapper(UserDao.class);<br> }
垃圾回收(销毁)
@After//用于测试方法执行之后执行<br> public void destroy() throws Exception {<br> //sqlSession.commit();<br> //手动设置自动提交,每次运行时<br> sqlSession.close();<br> in.close();<br> }<br>
注意映射文件UserDao.xml要放在resources下,不然就要配置指定资源插件
mbatis多表查询(非注解)
方法一:创建新的实体类AccountUser extends Account,映射配置文件使用resultType="accountuser",不推荐,不常用,非常麻烦的又创建了一个实体类AccountUser
public class AccountUser extends Account{<br> private String username;<br> private String address;
<select id="findAllAccount" resultType="accountuser"><br> select a.*,u.username,u.address from account a,user u where u.id = a.uid;<br> </select>
方法二:使用resultMap+collection标签(一对多时使用)
<resultMap id="userMap" type="user"><br> <id property="id" column="id"></id><br> <result property="username" column="username"></result><br> <result property="address" column="address"></result><br> <result property="sex" column="sex"></result><br> <result property="birthday" column="birthday"></result><br> <collection property="roles" ofType="role"><br> <id property="roleId" column="rid"></id><br> <result property="roleName" column="role_name"></result><br> <result property="roleDesc" column="role_desc"></result><br> </collection><br> </resultMap>
方法三:使用resultMap+association标签(一对一&多对一使用)<br>
<resultMap id="accountUserMap" type="account"><br> <!--为了避免两表联查时id重复,给子表id取别名为aid--><br> <id property="id" column="aid"></id><br> <result property="uid" column="uid"></result><br> <result property="money" column="money"></result><br> <association property="user" column="uid" javaType="user"><br> <id property="id" column="id"></id><br> <result property="username" column="username"></result><br> <result property="address" column="address"></result><br> <result property="sex" column="sex"></result><br> <result property="birthday" column="birthday"></result><br> </association><br> </resultMap>
注解开发
maven配置文件
pom.xml
<dependencies><br> <dependency><br> <groupId>org.mybatis</groupId><br> <artifactId>mybatis</artifactId><br> <version>3.5.6</version><br> </dependency><br> <dependency><br> <groupId>mysql</groupId><br> <artifactId>mysql-connector-java</artifactId><br> <version>5.1.49</version><br> </dependency><br> <dependency><br> <groupId>org.apache.logging.log4j</groupId><br> <artifactId>log4j</artifactId><br> <version>2.13.3</version><br> </dependency><br> <dependency><br> <groupId>junit</groupId><br> <artifactId>junit</artifactId><br> <version>4.11</version><br> </dependency><br> </dependencies>
mybatis主配置文件
SqlMapperConfig.xml
<?xml version="1.0" encoding="UTF-8" ?><br><!DOCTYPE configuration<br> PUBLIC "-//mybatis.org//DTD Config 3.0//EN"<br> "http://mybatis.org/dtd/mybatis-3-config.dtd"><br><configuration><br> <!--引入jdbc外部配置properties文件--><br> <properties resource="jdbcConfig.properties"/><br> <!--mybatis全局设置--><br> <settings><br> <!--控制日志输出到控制台--><br> <setting name="logImpl" value="STDOUT_LOGGING"/><br> <!--不写也行,高版本mybatis默认开启,但没使用,使用需注解@CacheNamespace(blocking = true)--><br> <setting name="cacheEnabled" value="true"/><br> </settings><br> <!--分别配置别名,不分大小写--><br> <typeAliases><br> <package name="com.tdcq.bean"/><br> </typeAliases><br> <environments default="mysql"><br> <environment id="mysql"><br> <transactionManager type="JDBC"/><br> <dataSource type="POOLED"><br> <property name="driver" value="${driver}"/><br> <property name="url" value="${url}"/><br> <property name="username" value="${username}"/><br> <property name="password" value="${password}"/><br> </dataSource><br> </environment><br> </environments><br> <!--指定接口--><br> <mappers><br> <package name="com.tdcq.dao"/><br> </mappers><br></configuration><br>
jdbc属性配置文件
jdbcConfig.properties
driver = com.mysql.jdbc.Driver<br>url = jdbc:mysql://localhost:3306/ssm<br>username = root<br>password = 147
javaBean
User.java
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
接口
UserDao.java
public interface UserDao {<br> /**<br> * 查询所有用户<br> *<br> * @return<br> */<br> @Select("select * from user")<br> List<User> findAll();
测试类
UserTest.java<br>
public class MybatisAnnotationTest {<br> private InputStream inputStream;<br> private SqlSessionFactory sqlSessionFactory;<br> private SqlSession sqlSession;<br> private UserDao userDao;<br> @Before//初始化<br> public void init() throws Exception {<br> //1.获取字节输入流<br> inputStream = Resources.getResourceAsStream("SqlMapperConfig.xml");<br> //2.根据字节输入流构建SqlSessionFactory<br> sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);<br> //3.根据SqlSessionFactory生产一个SqlSession<br> sqlSession = sqlSessionFactory.openSession();<br> //4.使用SqlSession获取Dao对象<br> userDao = sqlSession.getMapper(UserDao.class);<br> }<br> @After//释放资源<br> public void destroy() throws Exception {<br> sqlSession.commit();<br> sqlSession.close();<br> inputStream.close();<br> }<br> /**<br> * 查询所有<br> */<br> @Test<br> public void testfindAll() {<br> userDao.findAll();<br> }
一对一&多对一(使用注解)
实体类
public class Account implements Serializable {<br> private Integer id;<br> private Integer uid;<br> private Double money;<br> //多对一(mybatis中称为一对一)映射<br> //一个账户只能属于一个用户<br> private User user;
接口
/**<br> * 查询所有账户,并且获取每个账户所属的用户信息<br> * 一对一&多对一<br> * @return<br> */<br> @Select("select * from account")<br> //如果只有当前接口使用就不必起id = "accountUserMap"<br> @Results(id = "accountUserMap", value = {<br> //id=true表示主键<br> //property对应实体类属性名,column对应数据库列名<br> @Result(id = true, column = "id", property = "id"),<br> @Result(column = "uid", property = "uid"),<br> @Result(column = "money", property = "money"),<br> //把当前account表的uid作为下一个表的参数<br> @Result(column = "uid", property = "user",<br> //一对一(多对一)采用one = @One<br> //fetchType = FetchType.EAGER 加载类型为立即加载,<br> //一共有两种加载类型LAZY(懒加载,缓加载,也叫延迟加载),EAGER(立即加载),DEFAULT(不写默认立即加载);<br> one = @One(select = "com.tdcq.dao.UserDao.findById", fetchType = FetchType.EAGER))<br><br> })<br> List<Account> findAll();
测试
初始化略
/**<br> * 查询所有账户,并且获取每个账户所属的用户信息<br> * 一对一(多对一)立即加载<br> */<br> @Test<br> public void testfindAll() {<br> List<Account> accounts = accountDao.findAll();<br> for (Account account: accounts){<br> System.out.println(account);<br> System.out.println(account.getUser());<br> }<br> }
一对多(使用注解)
实体类
public class User implements Serializable {<br> private Integer id;<br> private String username;<br> private String address;<br> private String sex;<br> private Date birthday;<br> //一对多关系映射,一个用户对应多个账号<br> private List<Account> accounts;
接口
/**<br> * 查询所有用户,并且获取所有用户的所有账号<br> * 一对多<br> *<br> * @return<br> */<br> @Select("select * from user")<br> //只有当前接口使用的可以不定义id="userAccountMap"<br> @Results(value = {<br> @Result(id = true, column = "id", property = "id"),<br> @Result(column = "username", property = "username"),<br> @Result(column = "address", property = "address"),<br> @Result(column = "sex", property = "sex"),<br> @Result(column = "birthday", property = "birthday"),<br> //把当前user表中的id作为下一个sql语句的参数<br> @Result(column = "id", property = "accounts",<br> //一对多使用懒加载(延迟加载,缓加载)<br> many = @Many(select = "com.tdcq.dao.AccountDao.findAccountByUid", fetchType = FetchType.LAZY)<br> )<br> })<br> List<User> findAll2();
测试
/**<br> * 查询所有用户,并且获取所有用户的所有账号<br> * 一对多,延迟加载<br> */<br> @Test<br> public void testFindAll2(){<br> List<User> users = userDao.findAll2();<br> for (User user:users){<br> System.out.println("------------------------------------------------------------");<br> System.out.println(user);<br> System.out.println(user.getAccounts());<br> }<br> }
二级缓存
主配置文件SqlMapperConfig.xml
<settings><br> <!--不写也行,高版本mybatis默认开启,但没使用,使用需注解@CacheNamespace(blocking = true)--><br> <setting name="cacheEnabled" value="true"/><br> </settings>
接口
@CacheNamespace(blocking = true)<br>public interface UserDao {
测试
@Test<br>public void testFindOne2() {<br>SqlSession session = factory.openSession();<br>UserDao userDao = session.getMapper(UserDao.class);<br>User user = userDao.findById(47);<br>System.out.println(user);<br><br>session.close();//释放一级缓存<br>SqlSession session1 = factory.openSession();//再次打开session<br>UserDao userDao1 = session1.getMapper(UserDao.class);<br><br>User user1 = userDao1.findById(47);<br>System.out.println(user1);<br>System.out.println(user==user1);<br>session1.close();<br>}
一级缓存的生命周期
1.MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。<br>
2.如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;
3. 如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;
4.SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用;
一级缓存和二级缓存的区别
1.一级缓存使用SqlSession存储,二级缓存使用SqlSessionFactory存储<br>
2.一级缓存存储的是对象,二级缓存存储的是数据
0 条评论
下一页