What is MyBatis?
MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
MyBatis 是一个一流的持久性框架,它支持定制SQL、存储过程和高级映射。(是什么)
MyBatis 消除了几乎所有的JDBC代码和参数的手动设置和结果的检索。(优势)
MyBatis 可以使用简单的XML或注释来进行配置和映射原语,映射接口和Java pojo(普通旧式Java对象)到数据库记录。 (怎么做到的)
MyBatis使用需要一个动词(TestMapper),一个名词(Test),
Class.forName("com.mysql.cj.jdbc.Driver"); connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/gp?useUnicode=true&characterEncoding=utf-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", "root", "123456"); preparedStatement = connection.prepareStatement("SELECT * FROM test WHERE id = ?"); preparedStatement.setInt(1, id);
TestMapper testMapper = sqlSession.getMapper(TestMapper.class); return testMapper.insert(test);
可以采用 XML 的形式来配置,还可以采用 Annotation 的形式来配置
在一开始,每一个 XML 的 name 都对应 JAVA 实体类的一个属性!
public static SqlSession getSqlSession() throws FileNotFoundException { //配置文件 InputStream configFile = new FileInputStream( "E:\\workspace\\code\\git\\gupaoedu-mybatis\\src\\main\\java\\com\\gupaoedu\\mybatis\\demo\\mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configFile); //加载配置文件得到SqlSessionFactory return sqlSessionFactory.openSession(); } public static void main(String[] args) throws FileNotFoundException { TestMapper testMapper = getSqlSession().getMapper(TestMapper.class); Test test = testMapper.selectByPrimaryKey(1); }
约定优于配置。
pom.xml 配置 generator 插件
<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.3</version> <configuration> <configurationFile>${project.basedir}/src/main/resources/mybatis/generatorConfig.xml</configurationFile> </configuration> </plugin>
配置 generatorConfig.xml
执行 mvn mybatis-generator:generate
生成 Bean 和 Example
当 自动生成的文件和平时用的放到一起的时候,每一次逆向生成文件都容易和以前的产生冲突,每一次的回滚都是非常痛苦的。
我们能不能用架构来驾驭人,有些人你怎么说都没用,我就用一些规范来规范你,你要生成去另一个包里边去生成,永远不可能损害到我工程里边,防患于未然。有些人不是爱乱搞,他就是不会。
Example
的简单使用例子@Test public void example() { TestExample example = new TestExample(); example.setLimitClause("0,10"); List<com.gupao.dal.dao.Test> tests = mapper.selectByExample(example); System.out.printf(tests.toString()); }
Example
的不好的原因 大公司会有 DBA,他会去审查你的 SQL 语句,你要将你的 SQL 语句 + Mapper 都发给 DBA,然后让他帮你建表,然后过一遍。
然后你直接不用再写了 SQL,然后 DBA 也没办法审查你的 SQL 了。
example.createCriteria().andIdEqualTo(11).andNameEqualTo("");
和example.createCriteria().andNameEqualTo("").andIdEqualTo(11);
如果你建了索引,他是完全不同的速度 **。一个命中索引,一个没有命中索引。**很难查到这个问题,
Scope | |
---|---|
SqlSessionFactoryBuilder | method |
SqlSessionFactory | application |
SqlSession | request/method (可以 认为是线程级) |
Mapper | method |
SqlSessionFactoryBuilder
用一次,就返回了
//配置文件 InputStream configFile = new FileInputStream( "E:\\workspace\\code\\git\\gupaoedu-mybatis\\src\\main\\java\\com\\gupaoedu\\mybatis\\demo\\mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configFile); //加载配置文件得到SqlSessionFactory return sqlSessionFactory.openSession();
SqlSessionFactory
它是全局性的。
SqlSession
是一个方法,一次Request
和 Response
建立一次 SqlSession,可以认为是 线程级别的。
Mapper
method
Interface
Test selectByPrimaryKey(Integer id);
XML
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from test where id = #{id,jdbcType=INTEGER} </select>
@Select("select * from test where id = 2") Test selectByPrimaryKey(Integer id);
是互补式的兼容,没有优先,–> 是一种互补的形式。
同时存在启动会报错
Mapped Statements collection already contains value for com.darian.dal.dao.Testmapper.selectByPrimaryKey
Pros | Cons | |
---|---|---|
Mapper.xml | 1. 跟接口分离、统一管理 2. 复杂的语句可以不影响接口的可读性 |
1. 过多的 XML 文件 |
Annotation | 1. 接口就能够看到 Sql 语句,可读性高,不需要再去找 xml 文件,方便 | 1. 复杂的联合查询不好维护,代码的可读性差。 |
数据源,可以配置多个数据源
<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/gp?useUnicode=true&characterEncoding=utf-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments>
转换了,不需要做 数据库 和 JAVA 的处理
我们可以自定义 TypeHandler 转化:
枚举类型:Color
JAVA 英文 数据库 JAVA 中文 red 1 红色 green 2 绿色
sqlSessionFactoryBean.setTypeHandlers(new TypeHandler[]{new TestTypeHandle()});
基于某一个 SQL 来做的,不会影响你全局的东西。(BUG 比较难找)
<typeHandlers> <typeHandler handler="xxxx"></typeHandler> </typeHandlers>然后在某一个 SQL 上去配置对应的 typeHandler
拦截器。
@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
Mapper 在 Spring 管理下其实是单例,为什么可以是一个单例?
Keep it simple, keep Mappers in the method scope. The following example demonstrates this practice.
SqlSession session = sqlSessionFactory.openSession(); try { BlogMapper mapper = session.getMapper(BlogMapper.class); // do work } finally { session.close(); }官网上是这样写的。
SCOPE --> application
MyBatis 在 Spring 集成下没有 mapper 的 xml 文件会不会报错,为什么?
TypeHandler 手写
手写多个 Plugin,多个 interceptor 到底谁先执行? 顺序由谁去决定的?
来源于: https://javaguide.net
微信公众号:不止极客