MyBatis
ORMapping: Object Relationship Mapping 对象关系映射 Java 到 MySQL 的映射、以面向对象的思想来管理理数据库
简单使用 源生接口执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.dream.xiaobo</groupId > <artifactId > mybatis1</artifactId > <version > 1.0-SNAPSHOT</version > <dependencies > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.4.5</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.11</version > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.6</version > </dependency > </dependencies > <build > <resources > <resource > <directory > src/main/java</directory > <includes > <include > **/*.xml</include > </includes > </resource > </resources > </build > </project >
1 2 3 4 5 6 7 8 9 10 @Data @NoArgsConstructor @AllArgsConstructor public class User { private Long id; private String username; private String password; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?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 > <environments default ="mybatisTest" > <environment id ="mybatisTest" > <transactionManager type ="JDBC" > </transactionManager > <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.cj.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/db_mybatis?useUnicode=true& characterEncoding=UTF-8& serverTimezone=UTC" /> <property name ="username" value ="root" /> <property name ="password" value ="xiaobo" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="com/dream/xiaobo/mapper/userMapper.xml" > </mapper > </mappers > </configuration >
1 2 3 4 5 6 7 8 9 10 11 12 13 <?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.dream.xiaobo.mapper.userMapper" > <insert id ="save" parameterType ="com.dream.xiaobo.entity.User" > INSERT INTO user(username,password) VALUES(#{username },#{password }) </insert > </mapper >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void main (String[] args) { InputStream stream = MybastisTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml" ); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(stream); SqlSession sqlSession = sqlSessionFactory.openSession(); String url = "com.dream.xiaobo.mapper.userMapper.save" ; User user = new User(1L ,"xiaobo" ,"xiaboo" ); sqlSession.insert(url,user); sqlSession.commit(); }
mapper代理实现接口执行
1 2 3 4 5 6 7 8 9 10 11 12 13 public interface userRespository { public int save (User user) ; public int update (User user) ; public int deleteById (Long id) ; public List<User> findAll () ; public User findById (Long id) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?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.dream.xiaobo.respository.userRespository" > <insert id ="save" parameterType ="com.dream.xiaobo.entity.User" > INSERT INTO user(username,password) VALUES(#{username },#{password }) </insert > <update id ="update" parameterType ="com.dream.xiaobo.entity.User" > UPDATE user SET username = #{username },password = #{password } WHERE id = #{id } </update > <delete id ="deleteById" parameterType ="long" > DELETE FROM user WHERE id = #{id } </delete > <select id ="findAll" resultType ="com.dream.xiaobo.entity.User" > SELECT * FROM user </select > <select id ="findById" parameterType ="long" resultType ="com.dream.xiaobo.entity.User" > SELECT * FROM user WHERE id = #{id } </select > </mapper >
namespace:当前mapper的所在包名+文件名 insert:执行添加操作 delete:执行删除操作 update:执行更新操作 select:执行查询操作 id:与接口方法名相同 parameterType:与接口中对应方法的参数类型一致 resultType:与接口中对应方法的返回值类型一致
1 2 3 4 <mappers > <mapper resource ="com/dream/xiaobo/respository/userRespository.xml" > </mapper > </mappers >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public static void main (String[] args) { InputStream stream = TestMybatis.class.getClassLoader().getResourceAsStream("mybatis-config.xml" ); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(stream); SqlSession sqlSession = sqlSessionFactory.openSession(); userRespository mapper = sqlSession.getMapper(userRespository.class); List<User> list = mapper.findAll(); for (User user: list){ System.out.println(user); } User byId = mapper.findById(1L ); System.out.println(byId); mapper.save(new User(4L ,"wyb" ,"xiaobo" )); sqlSession.commit(); User user = mapper.findById(1L ); user.setUsername("wxh" ); user.setPassword("xiaobo" ); int update = mapper.update(user); sqlSession.commit(); mapper.deleteById(1L ); sqlSession.commit(); sqlSession.close(); }
mapper.xml parameterType 参数数据类型
基本数据类型
String类型
包装类类型
多个参数
1 2 3 <select id ="findByNameAndAge" > select * from user where username = #{arg0} and password = #{arg1} </select >
resultType 结果数据类型
基本数据类型
String数据类型
包装类数据类型
javaBean
级联查询 一对多的情况
1 2 3 4 5 6 7 8 9 10 11 @Data @AllArgsConstructor @NoArgsConstructor public class Student { private Long id; private String name; private String sex; private Integer age; private User user; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <resultMap id ="studentMap" type ="com.dream.xiaobo.entity.Student" > <id column ="id" property ="id" > </id > <result column ="name" property ="name" > </result > <result column ="sex" property ="sex" > </result > <result column ="age" property ="age" > </result > <association property ="user" javaType ="com.dream.xiaobo.entity.User" > <id column ="id" property ="id" > </id > <result column ="username" property ="username" > </result > <result column ="password" property ="password" > </result > </association > </resultMap > <select id ="findById2" resultMap ="studentMap" parameterType ="java.lang.Integer" > SELECT s.id,s.age,s.`name`,s.sex,u.username,u.`password` FROM student s,user u WHERE s.id = 1 AND s.userId = u.id </select > ```` > resultMap:是数据库与实体类形成映射关系 > id:主键字段映射 > result:普通字段映射 > column:数据库表字段名 > property:实体类字段名 > association:对象之间映射 **多对对的情况** - entity ```java @Data @AllArgsConstructor @NoArgsConstructor public class Student { private Long id; private String name; private String sex; private Integer age; private List<User > users; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <resultMap id ="studentMap" type ="com.dream.xiaobo.entity.Student" > <id column ="id" property ="id" /> <result column ="name" property ="name" /> <result column ="sex" property ="sex" /> <result column ="age" property ="age" /> <collection property ="users" ofType ="com.dream.xiaobo.entity.User" > <id column ="id" property ="id" /> <result column ="username" property ="username" /> <result column ="password" property ="password" /> </collection > </resultMap > <select id ="findById2" resultMap ="studentMap" parameterType ="java.lang.Integer" > SELECT s.id,s.age,s.`name`,s.sex,u.username,u.`password` FROM student s,user u WHERE s.id = 1 AND s.userId = u.id </select >
collention:集合对象映射 ofType:泛型内对象
MyBatis延迟加载
别名懒加载、惰性加载、可提高程序的运行效率、在某些特定的情况下去访问特定的数据库、在某些情况下不去访问某些表、在一定成都上减少了交互次数、根据具体的业务需求来动态减少数据表的查询工作
1 2 3 4 5 6 <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> <setting name ="lazyLoadingEnabled" value ="true" /> </settings >
MyBatis缓存 一级缓存:SqlSession级别、默认开启、不能关闭
创建SqlSession对象、在对象中有一个HashMap用于存储数据、不同的SqlSession之间缓存数据区域是互不影响的
一级缓存的作用域是SqlSession、当同一个SqlSession中执行两次相同的SQL语句、第一次执行完毕会将结果保存到缓存中、第二次查询时直接从缓存中获取
SqlSession执行了DML操作(INSERT、UPDATE、DELETE)、MyBatis必须将缓存清空保证数据的准确性、否则会出现读脏数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static void main (String[] args) { InputStream stream = TestMybatis.class.getClassLoader().getResourceAsStream("mybatis-config.xml" ); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(stream); SqlSession sqlSession = sqlSessionFactory.openSession(); userRespository mapper = sqlSession.getMapper(userRespository.class); User byId = mapper.findById(2L ); System.out.println(byId); sqlSession.close(); sqlSession = sqlSessionFactory.openSession(); mapper = sqlSession.getMapper(userRespository.class); System.out.println(mapper.findById(3L )); sqlSession.close(); }
二级缓存、Mapper级别、默认关闭、可以开启
多个SqlSession使用同一个Mapper的SQL语句操作数据库、得到的数据会存在二级缓存区、使用HashMap进行数据存储、SqlSession可以使用二级缓存、二级缓存是跨SqlSession的
二级缓存的多个SqlSession共享的、其作用域是Mapper的同一个namespace、不同的SQLSession执行的是相同的namspace下的SQL语句、参数也相等、第一次执行后会将数据保存到二级缓存中、第二次查询时也是直接从二级缓存中取出数据
mybatis自带二级缓存配置
1 2 3 4 5 6 7 8 <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> <setting name ="lazyLoadingEnabled" value ="true" /> <setting name ="cacheEnabled" value ="true" /> </settings >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Data @NoArgsConstructor @AllArgsConstructor public class User implements Serializable { private Long id; private String username; private String password; private List<Integer> ints; public User (Long id, String username, String password) { this .id = id; this .username = username; this .password = password; } }
第三方ehcache二级缓存配置
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-ehcache</artifactId > <version > 1.0.0</version > </dependency > <dependency > <groupId > net.sf.ehcache</groupId > <artifactId > ehcache-core</artifactId > <version > 2.4.3</version > </dependency >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <ehcache xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation ="../config/ehcache.xsd" > <diskStore /> <defaultCache maxElementsOnDisk ="10000000" eternal ="false" overflowToDisk ="false" timeToIdleSeconds ="120" timeToLiveSeconds ="120" diskExpiryThreadIntervalSeconds ="120" memoryStoreEvictionPolicy ="LRU" > </defaultCache > </ehcache >
1 2 3 4 5 6 7 8 <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> <setting name ="lazyLoadingEnabled" value ="true" /> <setting name ="cacheEnabled" value ="true" /> </settings >
1 2 3 4 5 6 7 <cache type ="org.mybatis.caches.ehcache.EhcacheCache" > <property name ="timeToIdleSeconds" value ="3600" /> <property name ="timeToLiveSeconds" value ="3600" /> <property name ="memoryStoreEvictionPolicy" value ="LRU" /> </cache >
MyBatis动态SQL
减少开发者的工作量、程序⾃自动根据业务参数来决定 SQL 的组成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <select id ="findByUser" parameterType ="com.dream.xiaobo.entity.User" resultType ="com.dream.xiaobo.entity.User" > SELECT * FROM user <where > <if test ="id != null" > id = #{id } </if > <if test ="username != null" > AND username = #{username } </if > <if test ="password != null" > AND password = #{password } </if > </where > </select >
where标签:自动判断是否要删除语句块中的AND关键字、如果检测到where直接和AND拼接、则自动删除 if标签:自动根据表达式结果来决定是否将对应的语句添加到SQL中、条件成立添加、反之不添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <select id ="findByUser" parameterType ="com.dream.xiaobo.entity.User" resultType ="com.dream.xiaobo.entity.User" > SELECT * FROM user <where > <choose > <when test ="id != null" > id = #{id } </when > <when test ="username != null" > AND username = #{username } </when > <when test ="password != null" > AND password = #{password } </when > </choose > </where > </select >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <select id ="findByUser" parameterType ="com.dream.xiaobo.entity.User" resultType ="com.dream.xiaobo.entity.User" > SELECT * FROM user <trim prefix ="where" prefixOverrides ="and" > <if test ="id != null" > id = #{id } </if > <if test ="username != null" > AND username = #{username } </if > <if test ="password != null" > AND password = #{password } </if > </trim > </select >
trim标签:prefix和suffix属性都会被用于生成实际的SQL语句、和标签内部语句进行拼接、但是如果语句前后出现prefixOverrides或者suffixOverrides属性汇总所指定的值、那么自动将其移除
1 2 3 4 5 6 7 8 9 10 11 12 <update id ="updateUser" parameterType ="com.dream.xiaobo.entity.User" > UPDATE user <set > <if test ="username != null" > username = #{username }, </if > <if test ="password != null" > password = #{password } </if > WHERE id = #{id } </set > </update >
set标签:用于更新
1 2 3 4 5 6 7 8 <select id ="findByUser2" parameterType ="com.dream.xiaobo.entity.User" resultType ="com.dream.xiaobo.entity.User" > SELECT * FROM user <where > <foreach collection ="ints" open ="id IN (" close =")" item ="id" separator ="," > #{id } </foreach > </where > </select >
foreach标签:迭代生成的一系列值、主要用于SQL的IN语句
MyBatis逆向工程
自动创建、实体类、自定义Mapper接口、Mapper.xml、支持基本的CRUD
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependencies > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.4.5</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.11</version > </dependency > <dependency > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-core</artifactId > <version > 1.3.2</version > </dependency > </dependencies >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration > <context id ="DB2Tables" targetRuntime ="MyBatis3" > <commentGenerator > <property name ="suppressAllComments" value ="true" /> </commentGenerator > <jdbcConnection driverClass ="com.mysql.cj.jdbc.Driver" connectionURL ="jdbc:mysql://localhost:3306/db_mybatis?useUnicode=true& charcaterEncoding=UTF-8& serverTimezone=UTC" userId ="root" password ="xiaobo" > </jdbcConnection > <javaTypeResolver > <property name ="forceBigDecimals" value ="false" /> </javaTypeResolver > <javaModelGenerator targetPackage ="com.dream.xiaobo.pojo" targetProject ="./src/main/java" > <property name ="enableSubPackages" value ="false" /> <property name ="trimStrings" value ="true" /> </javaModelGenerator > <sqlMapGenerator targetPackage ="mapper" targetProject ="./src/main/resources" > <property name ="enableSubPackages" value ="false" /> </sqlMapGenerator > <javaClientGenerator type ="XMLMAPPER" targetPackage ="com.dream.xiaobo.dao" targetProject ="./src/main/java" > <property name ="enableSubPackages" value ="false" /> </javaClientGenerator > <table schema ="user" tableName ="User" > </table > </context > </generatorConfiguration >
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void main (String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException { List<String> warnings = new ArrayList<String>(); boolean overwrite = true ; File configFile = new File("./src/main/resources/generatorConfig.xml" ); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null ); }
正确的开始、微小的长进、然后持续、嘿、我是小博、带你一起看我目之所及的世界……