初学MyBatis
MyBatis简介
引言
- Mybatis:是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到goodle code,并且改名为Mybatis,2013年11月迁移到Github
- Mybatis:是一个实现了数据持久化的开源框架,底层是对JDBC进行封装
- Mybatis:是半自动映射框架
- Mybatis是ORM框架(object、relational、mapping)对象关系模型,使用Mybatis,可以面向对象来操作持久化对象,ORM框架会通过映射关系将这些面向对象的操作转换成底层的SQL操作
持久化
- 数据持久是将内存中的数据保存到磁盘上加以固
化的过程 - 持久化的实现过程大多通过各种关系型数据库来完成。
持久层
- 在Java开发中对数据进行持久化的集合
第一个MyBatis
环境搭建
-
新建Maven工程,pom.xml
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.22</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!-- 解决找不到资源文件配置 --> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.XML</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build> -
新建数据表
create table user3( id int primary key auto_increment, username varchar(11), password varchar(11), age int ); -
新建数据表对应的实体类User(与数据表中的字段对应)
package com.sheep.pojo; public class User { private long id; private String username; private String password; private int age; ...请补充get、set } -
创建MyBatis的核心配置文件 config.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> <!-- 配置Mybatis运行环境 --> <environments default="mysql"> <environment id="mysql"> <!-- 配置JDBC事物管理 --> <transactionManager type="JDBC"/> <!-- POOLED配置JDBC数据源连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/user01?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true"/> <property name="username" value="root"/> <property name="password" value="123321"/> </dataSource> </environment> </environments> <!-- 注册UserMapper.XML --> <mappers> <mapper resource="com/sheep/mapper/UserMapper.XML"/> </mappers> </configuration>
原生接口开发
-
创建MyBatis的配置文件 Mapper.xml。MyBatis框架需要开发者自定义SQL语句,写在Mapper.xml文件中,实际开发 中,会为每个实体类创建对应的Mapper.xml,定义管理该对象数据的SQL。
-
调用MyBatis的原生接口执行添加操作
<?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.sheep.mapper.UserMapper"> <insert id="insert" parameterType="com.sheep.pojo.User"> insert into user3(username,password,age) values(#{username},#{password},#{age}) </insert> </mapper>- namespace属性通常设置为文件所在包+文件名的形式
- id是实际调用MyBatis方法时需要用到的参数
- parameterType是调用对应方法时参数的数据类型
- resultType是查询结果的返回类型
- insert标签表示执行添加操作
- update标签表示执行更新操作
- select标签表示执行查询操作
- delete标签表示执行删除操作
-
在全局配置文件config.xml中注册user3Mapper.xml
<!-- 注册User3Mapper。xml --> <mappers> <mapper resource="com/sheep/mapper/UserMapper.XML"/> </mappers> -
调用MyBatis原生接口进行操作
import com.sheep.pojo.User; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test { public static void main(String[] args) { //加载配置文件 InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.XML"); //创建SessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //SqlSessionFactoryBuilder对象的Build方法通过配置文件创建会话工厂SqlSessionFactory SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); //通过工厂获取SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //通过SqlSession调用User3Mapper中的SQL语句 //com.sheep.mapper.UserMapper.insert=com.sheep.mapper.UserMapper+.insert(statement标签的id属性) String statement = "com.sheep.mapper.UserMapper.insert"; User user = new User(1L,"梅西","123123",22); sqlSession.insert(statement,user); //提交事务 sqlSession.commit(); //释放资源 sqlSession.close(); } }
- 加载MyBatis配置文件
- 创建SqlSessionFactoryBuilder对象
- 通过SqlSessionFactoryBuilder对象创建会话工厂SqlSessionFactory
- 通过工厂获取SqlSession
- 通过SqlSession获取Mapper映射文件全类名+statement标签中的id属性调用SQL
- 提交事务、释放资源
代理接口开发
通过MyBatis代理实现自定义接口
-
自定义接口
package com.sheep.repository; import com.sheep.pojo.User; import java.util.List; public interface UserIntf { public int insert(User user); public int update(User user); public int deleteById(long id); public List<User> findAll(); public User findById(long id); } -
创建接口对应的UserIntf.XML,定义接口方法对应的SQL语句。
statement标签(即<mapper>中的标签)可根据SQL执行的业务选择insert、delete、update、select。
MyBatis框架会根据规则自动创建接口实现类的代理对象。
规则:
- Mapper.xml中namespace为接口的全类名。
- Mapper.xml中statement的id为接口中对应的方法名。
- Mapper.xml中statement的parameterType和接口中对应方法的参数类型一致。
- Mapper.xml中statement的resultType和接口中对应的返回值类型一致。
<?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.sheep.repository.UserIntf"> <insert id="insert" parameterType="com.sheep.pojo.User"> insert into user3(username,password,age) values(#{username},#{password},#{age}) </insert> <update id="update" parameterType="com.sheep.pojo.User"> update user3 set username=#{username},password=#{password},age=#{age} where id=#{id} </update> <delete id="deleteById" parameterType="java.lang.Long"> delete from user3 where id=#{id} </delete> <select id="findAll" resultType="com.sheep.pojo.User"> select * from user3 </select> <select id="findById" parameterType="java.lang.Long" resultType="com.sheep.pojo.User"> select * from user3 where id=#{id} </select> </mapper> -
在全局配置文件config.xml中注册UserIntf.XML
<!-- 注册User3Mapper.xml --> <mappers> <mapper resource="com/sheep/repository/UserIntf.XML"/> </mappers> -
调用接口的代理对象完成相关的业务操作
import com.sheep.pojo.User; import com.sheep.repository.UserIntf; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; import java.util.List; public class Test2 { public static void main(String[] args) { InputStream resource = Test2.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); /** * 获取实现接口的代理对象 * */ UserIntf mapper = sqlSession.getMapper(UserIntf.class); /** * 查询 * */ List<User> all = mapper.findAll(); for (User user:all){ System.out.println(user); } sqlSession.close(); /** * 添加 * */ User user = new User(1L, "C罗", "1235679", 34); mapper.insert(user); sqlSession.commit(); sqlSession.close(); /** * 更改 * */ User user2 = mapper.findById(3L); user.setUsername("石磊"); user.setPassword("666666"); user.setAge(23); int update = mapper.update(user2); sqlSession.commit(); sqlSession.close(); /** * 根据id查询对象 * */ User byId = mapper.findById(2L); System.out.println(byId); sqlSession.close(); /** * 删除 * */ int i = mapper.deleteById(3L); System.out.println(i); sqlSession.commit(); sqlSession.close(); } } -
增删改必须提交事务
MyBatis的四大神兽
SqlSessionFactory
SqlSessionFactory是MyBatis框架中十分重要的对象,它是单个数据库映射关系经过编译后的内存镜像,其主作用是创建SqlSession。SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来创建,而SqlSessionFactoryBuilder则可以通过XML配置文件构建出SqlSessionFactory的实例
//创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //SqlSessionFactoryBuilder对象的Build方法通过配置文件创建会话工厂SqlSessionFactory SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSessionFactory对象是线程安全的,一旦被创建,在整个应用执行期间都会存在。
如果多次创建同一个数据库的SqlSessionFactory,那么数据库资源将很容易被耗尽,所有通常每一个数据库都会对应一个SqlSessionFactory,所有在构建SqlSessionFactory实例时,建议使用单例模式。
SqlSession
SqlSession是应用程序与持久层之间执行交互操作的一个单线程对象,主要用作持久化操作。
SqlSession对象包含了数据库中所有执行SQL操作的所有方法,底层封装了JDBC连接。
每一个线程都应该有一个自己的SqlSession实例,并且该实例是不能被共享的。SqlSession实例是线程不安全的,因此其使用范围最好在一次请求或一个方法中,绝不能将其放在一个类的静态字段、实例字段或任何管理范围(Servlt的HttpSession)中使用。使用完SqlSession记得关闭。
Config.xml
Config.xml配置文件中<configuration>元素是根元素,<configuration>的子元素必须按照以下顺序配置,否则会报错。
<configuration> <properties><!-- 数据库的连接属性 --> <settings><!-- 开启二级缓存、开启延时加载 --> <typeAliases><!-- 设置别名 --> <typeHandlers><!-- 设置一个参数、或者从结果集中取出一个值 --> <objectFactory><!-- 对象工厂 --> <plugins><!-- 插件 --> <environments><!-- 数据环境配置 --> <databaseIdProvider> <mappers><!-- 指定Mapper文件的映射位置 --> </configuration>
Mapper.xml
-
statement标签:<select>、<insert>、<update>、<delete>、<sql>、<cache>、<cache-ref>、<resultMap>。
-
<select>、<insert>、<update>、<delete>标签分别对应查询、添加、更改、删除操作
-
CRUD中的属性
-
parameterType:参数类型
-
基本数据类型,通过id查询User
public User findById(long id);<select id="findById" parameterType="java.lang.Long"resultType="com.sheep.pojo.User"> select * from user3 where id=#{id} </select>public static void main(String[] args) { InputStream resource=Test2.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder(); SqlSessionFactory build=sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession=build.openSession(); //获取接口代理对象 UserIntf mapper = sqlSession.getMapper(UserIntf.class); User user = mapper.findById(2L); System.out.println(user); sqlSession.close(); } -
String类型,通过name查询User
public User findByName(String username);<select id="findByName" parameterType="java.lang.String" resultType="com.sheep.pojo.User"> select * from user3 where username=#{username} </select>User user = mapper.findByName("内马尔"); System.out.println(user); sqlSession.close(); -
包装类,通过id查询User
public User findById2(long id);<select id="findById2" parameterType="java.lang.Long"resultType="com.sheep.pojo.User"> select * from user3 where id=#{id} </select>User user = mapper.findById(2L); System.out.println(user); sqlSession.close(); -
多个参数
public User findByNameAndAge(String username,int age);<select id="findByNameAndAge" resultType="com.sheep.pojo.User"> select * from user3 where username=#{param1} and age=#{param2} <!--有多个参数时不用写parameterType参数但取值时要使用#{param1}、#{param2}--> </select>User user = mapper.findByNameAndAge("C罗", 34); System.out.println(user); sqlSession.close(); -
javaBean做参数
public int update(User user);<update id="update" parameterType="com.sheep.pojo.User"> update user3 set username=#{username},password=#{password},age=#{age} where id=#{id} </update>User user2 = mapper.findById(3L); user.setUsername("石磊"); user.setPassword("666666"); user.setAge(23); int update = mapper.update(user2); sqlSession.commit(); sqlSession.cose(); -
Map参数
public User findUser(Map<Object, Object> map);<select id="findUser" parameterType="map" resultType="com.sheep.pojo.User"> select * from user3 where id=#{abcdefg} and age=#{hijklmn} </select>Map<Object, Object> map = new HashMap<>(); map.put("abcdefg",4); map.put("hijklmn",29); User user = mapper.findUser(map); System.out.println(user); sqlSession.close();当根据多个字段查询时使用Map集合更加方便。而且SQL语句中参数名只要与Map集合中的Key相同即可。
-
-
resultType:结果类型
-
基本数据类型
public int count();<select id="count" resultType="int"> select count(id) from user3 </select>int count = mapper.count(); System.out.println(count); sqlSession.close(); -
包装类
public Integer count2();<select id="count2" resultType="java.lang.Integer"> select count(id) from user3 </select>Integer integer = mapper.count2(); System.out.println(integer); sqlSession.close(); -
String类型,通过id查询User的username
public String findNameById(long id);<select id="findNameById" resultType="String"> select username from user3 where id=#{id} </select>String name = mapper.findNameById(5L); System.out.println(name); sqlSession.close(); -
JavaBean类型返回集合类型
public List<User> findAll();<select id="findAll" resultType="com.sheep.pojo.User"> select * from user3 </select>List<User> all = mapper.findAll(); for (User user:all){ System.out.println(user); } sqlSession.close(); -
javaBean类型
public User findById(long id);<select id="findById" parameterType="java.lang.Long" resultType="com.sheep.pojo.User"> select * from user3 where id=#{id} </select>User byId = mapper.findById(2L); System.out.println(byId); sqlSession.close();
-
Limit分页
引言
客服端传过来的start(页码),pageSize(每页显示的数据)两个参数去分页查询数据库,MySQL数据库提供了分页的函数limit m,n,但是该函数的用法和我们的需求不一样,我们要根据真实需求来写适合我i吗的分页语句。
例如:每页10条显示数据,
查询第1条SQL语句是:select * from table limit 0,10; = select * from table limit(1-1)*10,10;
查询第11条SQL语句是:select * from talbe limit 10,10; = select * from table limit(2-1)*10,10;
查询第21条SQL语句是:select * from table limit 20,10; = select * from table limit(3-1)*10,10;
limit(起始位,步长);
通过上面的分析,可以得出符合需求的分页sql格式:select * from table limit(start-1)*pageSize,pageSize;
简单案例
-
建表
create table user3( id int primary key auto_increment, username varchar(11), password varchar(11), age int ); -
实体类
public class User{ private long id; private String username; private String password; private int age; ...请补充get、set } -
创建接口
public List<User> getUserByLimit(Map<Object, Object> map); -
mapper代理实现
<select id="getUserByLimit" resultType="com.sheep.pojo.User"> select * from user3 limit #{startIndex},#{pageSize} </select> -
测试
public static void main(String[] args) { InputStream resource = Test2.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); Map<Object, Object> map = new HashMap<>(); map.put("startIndex",0); map.put("pageSize",5); List<User> userByLimit = mapper.getUserByLimit(map); for (User user:userByLimit){ System.out.println(user); } } -
结果
==> Preparing: select * from user3 limit ?,? ==> Parameters: 0(Integer), 4(Integer) <== Columns: id, username, password, age <== Row: 1, 梅西, 123123, 22 <== Row: 2, 梅西, 123123, 22 <== Row: 4, 内马尔, 1235679, 29 <== Row: 5, C罗, 1235679, 34 <== Total: 4 user3{id=1, username='梅西', password='123123', age=22} user3{id=2, username='梅西', password='123123', age=22} user3{id=4, username='内马尔', password='1235679', age=29} user3{id=5, username='C罗', password='1235679', age=34}
级联操作
mybatis级联:通过数据库中的表可以描述数据之间的关系,在Java中,对象也可以进行关系描述
/**
*一对一
*/
Class A{ Class B{
B b; A a;
} }
/**
*一对多
*/
Class A{ Class B{
List<B> b; A a;
} }
/**
*多对多
*/
Class A{ Class B{
List<B> b; List<A> a;
} }
一对一
-
创建表
mysql> create table white( -> id int primary key auto_increment, -> name varchar(5) -> ); mysql> create table black( -> id int primary key auto_increment, -> name varchar(10), -> wid int, -> foreign key(wid) references white(id) -> ); -
创建 表对应的实体类
package com.sheep.pojo; public class Black{ private int id; private String name; private White white; ...请补充get、set }package com.sheep.pojo; public class White { private int id; private String name; private Black black; ...请补充get、set } -
创建接口
package com.sheep.repository; import com.sheep.pojo.Black; public interface BlackRepository { public Black findById(long id); } -
创建接口对应的代理对象
<?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.sheep.repository.BlackRepository"> <resultMap id="blackMap" type="com.sheep.pojo.Black"> <result column="bname" property="name"/> <association property="white" javaType="com.sheep.pojo.White"> <result column="wname" property="name"/> </association> </resultMap> <select id="findById" parameterType="long" resultMap="blackMap"> select b.name bname,w.name wname from black b,white w where b.id=#{id} and b.wid=w.id; </select> </mapper> -
在全局备注文件中注册代理对象
<mapper resource="com/sheep/repository/BlackRepository.XML"/> -
测试
import com.sheep.pojo.Black; import com.sheep.repository.BlackRepository; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test7 { public static void main(String[] args) { InputStream resource = Test7.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); BlackRepository mapper = sqlSession.getMapper(BlackRepository.class); Black byId = mapper.findById(5l); System.out.println(byId); } }结果
Black{id=0, name='z长空', white=White{id=0, name='大陆', black=null}}
一对多
-
创建表
mysql> create table classes( -> id int primary key auto_increment, -> name varchar(10) -> ); mysql> create table student( -> id int primary key auto_increment, -> name varchar(10), -> cid int, -> foreign key(cid) references classes(id) -> ); -
创建数据库对应的实体类
Classes、班级
package com.sheep.pojo; import java.util.List; public class Classes { private long id; private String name; private List<Student> studentList; ...请补充get、set }Student、班级
package com.sheep.pojo; public class Student { private long id; private String name; private Classes classes; ...请补充get、set } -
创建接口
package com.sheep.repository; import com.sheep.pojo.Student; public interface StudentRepository { public Student findById(long id); } -
创建代理类对应的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.sheep.repository.StudentRepository"> <resultMap id="studentMap" type="com.sheep.pojo.Student"> <id column="id" property="id"/> <result column="name" property="name"/> <association property="classes" javaType="com.sheep.pojo.Classes"> <id column="cid" property="id"/> <result column="cname" property="name"/> </association> </resultMap> <select id="findById" parameterType="long" resultMap="studentMap"> select stu.id,stu.name,cla.id as cid,cla.name as cname from student stu,classes cla where stu.id=#{id} and stu.cid = cla.id </select> </mapper>xml中SQL语句
select stu.id,stu.name,cla.id as cid,cla.name as cname from student stu,classes cla where stu.id=#{id} and stu.cid = cla.id < -- 根据stu、cla查找stu.id为#{id}并且stu.cid = cla.id的记录,--> < -- 并将该记录的stu.id、stu.name、cla.cid、cla.cname返回-- >xml中<resultMap>标签:
<resultMap id="studentMap" type="com.sheep.pojo.Student"> <id column="id" property="id"/> <result column="name" property="name"/> <association property="classes" javaType="com.sheep.pojo.Classes"> <id column="cid" property="id"/> <result column="cname" property="name"/> </association> </resultMap>- 在级联查询中SQL语句查询的结果,无法直接与实体类映射,需要使用<resultMap/>标签与查询结果间接映射
- <resultMap id="间接映射id" type="代理接口的返回类型"/>
- <id column="查询结果字段主键" property="d对应的实体类参数"/>
- <result column="查询结果字段" property=对应的实体类参数""/>
- <collection property="实体类集合变量" ofType="集合泛型"/>
-
在config.xml中注册
<mapper resource="com/sheep/repository/StudentRepositoy.XML"/> -
测试
import com.sheep.pojo.Student; import com.sheep.repository.StudentRepository; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test3 { public static void main(String[] args) { InputStream resource = Test2.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); StudentRepository mapper = sqlSession.getMapper(StudentRepository.class); Student student = mapper.findById(1L); System.out.println(student); } }结果
Student{id=1, name='梅西', classes=Classes{id=1, name='z阿根廷', studentList=null}}
多对一
-
创建接口
package com.sheep.repository; import com.sheep.pojo.Classes; public interface ClassesRepository { public Classes findById(long id); } -
创建代理类对应的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.sheep.repository.ClassesRepository"> <resultMap id="classesMap" type="com.sheep.pojo.Classes"> <id column="id" property="id"/> <result column="name" property="name"/> <collection property="studentList" ofType="com.sheep.pojo.Student"> <id column="sid" property="id"/> <result column="sname" property="name"/> </collection> </resultMap> <select id="findById" parameterType="long" resultMap="classesMap"> select c.id,c.name,s.id as sid,s.name as sname from classes c,student s where c.id=#{id} and c.id=s.cid; </select> </mapper>- 在级联查询中SQL语句查询的结果,无法直接与实体类映射,需要使用<resultMap/>标签与查询结果间接映射
- <resultMap id="间接映射id" type="代理接口的返回类型"/>
- <id column="查询结果字段主键" property="d对应的实体类参数"/>
- <result column="查询结果字段" property=对应的实体类参数""/>
- <collection property="实体类集合变量" ofType="集合泛型"/>
-
在config.xml中注册
<mapper resource="com/sheep/repository/ClassesRepository.XML"/> -
import com.sheep.pojo.Classes; import com.sheep.repository.ClassesRepository; import com.sheep.repository.StudentRepository; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test4 { public static void main(String[] args) { InputStream resource = Test2.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); ClassesRepository mapper = sqlSession.getMapper(ClassesRepository.class); Classes byId = mapper.findById(3l); System.out.println(byId); } }结果
Classes{id=3, name='z巴西', studentList=[Student{id=6, name='内马尔', classes=null}, Student{id=7, name='小罗', classes=null}, Student{id=8, name='外星人', classes=null}, Student{id=9, name='贝利', classes=null}]}
多对多
-
创建三个表
mysql> create table customer( -> id int primary key auto_increment, -> name varchar(10) -> ); mysql> create table goods( -> id int primary key auto_increment, -> name varchar(15) -> ); mysql> create table customer_goods( -> id int primary key auto_increment, -> cid int, -> gid int, -> foreign key(cid) references customer(id), -> foreign key(gid) references goods(id) -> ); mysql> select * from customer; +----+--------+ | id | name | +----+--------+ | 1 | 梅西 | | 2 | C罗 | | 3 | 詹姆斯 | | 4 | 张继科 | | 5 | 超级丹 | +----+--------+ mysql> select * from customer_goods; +----+------+------+ | id | cid | gid | +----+------+------+ | 1 | 1 | 1 | | 2 | 2 | 1 | | 3 | 3 | 2 | | 4 | 4 | 3 | | 5 | 5 | 4 | | 6 | 1 | 4 | | 7 | 2 | 2 | | 8 | 4 | 1 | | 9 | 5 | 2 | | 10 | 2 | 4 | +----+------+------+ mysql> select * from goods; +----+--------+ | id | name | +----+--------+ | 1 | 足球 | | 2 | 篮球 | | 3 | 兵乓球 | | 4 | 羽毛球 | +----+--------+ -
创建表customer、goods对应的实体类
package com.sheep.pojo; import java.util.List; public class Customer { private long id; private String name; private List<Goods> goodsList; ...请补充get、set }package com.sheep.pojo; import java.util.List; public class Goods { private long id; private String name; private List<Customer> customerList; public Goods(){} ...请补充get、set } -
创建接口(客户对商品)
package com.sheep.repository; import com.sheep.pojo.Customer; public interface CustomerRepository { public Customer findById(long id); } -
新建接口的代理对象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.sheep.repository.CustomerRepository"> <resultMap id="customerMap" type="com.sheep.pojo.Customer"> <result column="cname" property="name"/> <collection property="goodsList" ofType="com.sheep.pojo.Goods"> <result column="gname" property="name"/> </collection> </resultMap> <select id="findById" parameterType="long" resultMap="customerMap"> select c.name cname,g.name gname from customer c,goods g,customer_goods cg where c.id=#{id} and c.id=cg.cid and g.id=cg.gid; </select> </mapper> -
在config.xml中配置
<mapper resource="com/sheep/repository/CustomerRepository.XML"/> -
测试
import com.sheep.pojo.Customer; import com.sheep.repository.CustomerRepository; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test5 { public static void main(String[] args) { InputStream resource = Test2.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); CustomerRepository mapper = sqlSession.getMapper(CustomerRepository.class); Customer byId = mapper.findById(1l); System.out.println(byId); } }结果
Customer{id=0, name='超级丹', goodsList=[Goods{id=0, name='羽毛球', customerList=null}, Goods{id=0, name='篮球', customerList=null}]} -
创建接口(商品对客户)
package com.sheep.repository; import com.sheep.pojo.Goods; public interface GoodsRepository { public Goods findById(long id); } -
创建接口代理对象
<?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.sheep.repository.GoodsRepository"> <resultMap id="goodsMap" type="com.sheep.pojo.Goods"> <result column="gname" property="name"/> <collection property="customerList" ofType="com.sheep.pojo.Customer"> <result column="cname" property="name"/> </collection> </resultMap> <select id="findById" parameterType="long" resultMap="goodsMap"> select g.name gname,c.name cname from customer c,goods g,customer_goods cg where g.id=#{id} and g.id=cg.cid and c.id=cg.gid; </select> </mapper> -
在XML中注册
<mapper resource="com/sheep/repository/GoodsRepository.XML"/> -
测试
import com.sheep.pojo.Goods; import com.sheep.repository.GoodsRepository; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test6 { public static void main(String[] args) { InputStream resource = Test6.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); GoodsRepository mapper = sqlSession.getMapper(GoodsRepository.class); Goods byId = mapper.findById(1l); System.out.println(byId); } }结果
Goods{id=0, name='足球', customerList=[Customer{id=0, name='梅西', goodsList=null}, Customer{id=0, name='张继科', goodsList=null}]}
总结
在级联查询中当返回的结果中有基本数据类型、List、实体类时。不能直接映射,只能使用间接映射。
当返回的结果中包含实体类时使用<resultMap>、<association>。
当返回的结果中包含List时使用<resultMap>、<collection>。
动态SQL
-
创建表
CREATE TABLE `trends` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(5) DEFAULT NULL, `password` varchar(10) DEFAULT NULL, `age` varchar(5) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 -
创建表对应的实体类
public class Trends { private int id; private String name; private String password; private String age; //ids变量用于<foreach/> private List<Long> ids; }
.<if>
-
if
public int sel(Trends trends);if标签:判断语句,相当于Java中的if,如果test="name !=null and name!='' 为 true 则执行该代码。否则不执行
<!-- if语句 --> <select id="sel" parameterType="com.sheep.pojo.Trends" resultType="int"> select * from trends where 1=1 <if test="name !=null and name!=''"> and name=#{name} </if> <if test="password != null and password != ''"> and password=#{password} </if> <if test="age != null and age !=''"> and age=#{age} </if> </select>/** if语句 */ Trends trends = new Trends(); trends.setName("梅西"); trends.setPassword("666"); trends.setAge("36"); mapper.sel(trends); -
if+where
public List<Trends> AllSelect(Trends trends);where标签:如果它包含的标签中有返回值,就插入一个where。如果标签返回的内容是and或or开头的则它会踢出。
<!-- if-where --> <!-- if-trim与if-where效果基本相等 --> <select id="AllSelect" parameterType="com.sheep.pojo.Trends" resultType="com.sheep.pojo.Trends"> select * from trends <where> <if test="name != null and name != ''"> and name=#{name} </if> <if test="password != null and password != ''"> and password=#{password} </if> </where> <trim prefix="where" prefixOverrides="and | or"> <if test="name != null and name != ''"> and name=#{name} </if> <if test="password != null and password != ''"> and password=#{password} </if> </trim> </select>/** if-where 、if-trim*/ Trends trends = new Trends(); List<Trends> listTrends = mapper.AllSelect(trends); for (Trends trends2:listTrends){ System.out.println(trends2); } -
if+trim
public List<Trends> AllSelect(Trends trends);trim标签:是一个格式化的标记,可以完成set或者是where标记的功能
prefix="where":如果有返回值就在返回值前面加where
prefixOverrides="and | or":如果返回值开头是and | or就踢出
<!-- if-where --> <!-- if-trim与if-where效果基本相等 --> <select id="AllSelect" parameterType="com.sheep.pojo.Trends" resultType="com.sheep.pojo.Trends"> select * from trends <trim prefix="where" prefixOverrides="and | or"> <if test="name != null and name != ''"> and name=#{name} </if> <if test="password != null and password != ''"> and password=#{password} </if> </trim> </select>/** if-where 、if-trim*/ Trends trends = new Trends(); List<Trends> listTrends = mapper.AllSelect(trends); for (Trends trends2:listTrends){ System.out.println(trends2); } -
if+set
public void update(Trends trends);set标签:专门用于更新操作,如果第一个条件为 false 则不执行该条件,继续判断下面语句。
<!-- if-set...用于update语句 --> <select id="update" parameterType="com.sheep.pojo.Trends"> update trends <set> <if test="name !=null and name !=''"> name=#{name}, </if> <if test="age !=null and name !=''"> age=#{age} </if> </set> where id=#{id} </select>/** if-set */ Trends trends = mapper.trendsAll(3); System.out.println(trends); trends.setName("小C罗"); trends.setAge("18"); mapper.update(trends); sqlSession.commit(); sqlSession.close();
.<choose>
-
public Trends findTrends(Trends trends);<choose>语句:类似于Java当中switch...case...default语句,如果when标签中test为true则赋值该SQL如果都不为真则最终执行otherwise标签中的代码。
<!-- <choose><when><otherwise> --> <select id="findTrends" parameterType="com.sheep.pojo.Trends" resultType="com.sheep.pojo.Trends"> select * from trends <where> <choose> <when test="id != null and id != ''"> and id=#{id} </when> <when test="name != null and name !=''"> and name=#{name} </when> <when test="password !=null and password !=''"> and password=#{password} </when> <otherwise> and age=#{age} </otherwise> </choose> </where> </select>/**<choose><when><otherwise>*/ Trends trends = new Trends(); trends.setAge("18"); Trends trends1 = mapper.findTrends(trends); System.out.println(trends1);
<where>、<trim>、<set>
- <where>:根据条件添加where,或踢出and | or
- <trim>:根据条件添加where,或踢出and | or
- <set>:用于更新操作(update)根据条件添加set。
.<foreach>
-
public List<Trends> findByAllId(Trends trends);在实体类中添加属性ids
//ids变量用于<foreach/> private List<Long> ids;foreach标签:当sql语句为:select * from user where id=1 or id=2 or id=3; || select * from user where id in (1,2,3);
就可以使用foreach标签类似于Java中的for循环
collection="ids":被循环的变量(array、list、或collection、Map集合的键、POJO包装类中的数组或集合类型的属性名)。
open="id in (":以什么符号开头(相当于从or语句开始)
separator=",":各个元素的间隔符
close=")":以什么符号结尾
item="id":将容器变量赋值给该属性并将该属性与sql语句中的属性关联。
<select id="findByAllId" parameterType="com.sheep.pojo.Trends" resultType="com.sheep.pojo.Trends"> select * from trends <where> <foreach collection="ids" item="id" open="id in (" separator="," close=")"> #{id} </foreach> </where> </select>/**<foreach>*/ Trends trends1 = new Trends(); List<Long> list = new ArrayList<>(); list.add(1L); list.add(2L); list.add(3L); trends1.setIds(list); List<Trends> byAllId = mapper.findByAllId(trends1); for (Trends trends:byAllId){ System.out.println(trends); }
SQL片段引用
-
public int findAll(Trends trends);<!-- 引用sql片段 --> <!-- 被引用的是sql标签 --> <sql id="findAllTrends"> <if test="name !=null and name !=''"> and name=#{name} </if> <if test="password !=null and password != ''"> and password=#{password} </if> <if test="age !=null and age !=''"> and age=#{age} </if> </sql> <select id="findAll" parameterType="com.sheep.pojo.Trends" resultType="int"> select * from trends <trim prefix="where" prefixOverrides="and | or"> <include refid="findAllTrends"></include> </trim> </select>/** 引用sql片段 */ Trends trends = new Trends(); trends.setName("梅西"); trends.setPassword("666"); trends.setAge("36"); int all = mapper.findAll(trends); System.out.println(all); }
浅聊MyBatis延迟加载
什么是延迟加载?
延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机(延迟加载也称懒加载,就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据)。在Mybatis中经常用到关联查询,但是并不是任何时候都需要立即返回关联查询结果。比如查询用户信息,并不一定需要及时返回用户下对应的账户信息,再比如查询商品分类信息并不一定要及时返回该类别下有哪些产品,这种情况一下需要一种机制,当需要查看时,再执行查询,返回需要的结果集,这种需求在Mybatis中可以使用延迟加载机制来实现。延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率
如何使用
不开启延迟加载
-
表classes、student
mysql> create table classes( -> id int primary key auto_increment, -> name varchar(10) -> ); mysql> create table student( -> id int primary key auto_increment, -> name varchar(10), -> cid int, -> foreign key(cid) references classes(id) -> ); -
表对应的实体类Student、Classes
public class Student { private long id; private String name; private Classes classes; ...请补充get、set }public class Classes { private long id; private String name; private List<Student> studentList; ...请补充get、set } -
创建接口ClassesRepository、StudentRepository
package com.sheep.repository; import com.sheep.pojo.Classes; public interface ClassesRepository { public Classes findByIdLazy(long id); }package com.sheep.repository; import com.sheep.pojo.Student; public interface StudentRepository { public Student findById2(long id); } -
创建接口的代理对象ClassesRepository.XML、StudentRepository.XML
<?xml version="1.0" encoding="UTF8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- ClassesRepository.XML --> <mapper namespace="com.sheep.repository.ClassesRepository"> <select id="findByIdLazy" parameterType="long" resultType="com.sheep.pojo.Classes"> select * from classes where id=#{id} </select> </mapper><?xml version="1.0" encoding="UTF8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- StudentRepository.XML --> <mapper namespace="com.sheep.repository.StudentRepository"> <resultMap id="studentMap2" type="com.sheep.pojo.Student"> <id column="id" property="id"/> <result column="name" property="name"/> <association property="classes" javaType="com.sheep.pojo.Classes" select="com.sheep.repository.ClassesRepository.findByIdLazy" column="cid"> <!-- 把当前结果集的cid当作条件当作com.sheep.repository.ClassesRepository.findByIdLazy方法的参数查询并返回结果 --> </association> </resultMap> <select id="findById2" parameterType="long" resultMap="studentMap2"> select * from student where id=#{id} </select> </mapper> -
测试
import com.sheep.pojo.Student; import com.sheep.repository.StudentRepository; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test3 { public static void main(String[] args) { InputStream resource = Test2.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resource); SqlSession sqlSession = build.openSession(); //通过StudentRepository运行时类创建对象 StudentRepository mapper = sqlSession.getMapper(StudentRepository.class); Student student2 = mapper.findById2(2L); System.out.println(student2.getName()); } }运行
==> Preparing: select * from student where id=? ==> Parameters: 2(Long) <== Columns: id, name, cid <== Row: 2, 保罗.迪巴拉, 1 ====> Preparing: select * from classes where id=? ====> Parameters: 1(Long) <==== Columns: id, name <==== Row: 1, z阿根廷 <==== Total: 1 <== Total: 1 保罗.迪巴拉 -
在config.xml配置开启延时加载
<settings> <!-- 设置SQL打印 --> <setting name="logImpl" value="STDOUT_LOGGING"/> <!-- 开启延迟加载 --> <setting name="lazyLoadingEnabled" value="true"/> </settings>运行
==> Preparing: select * from student where id=? ==> Parameters: 2(Long) <== Columns: id, name, cid <== Row: 2, 保罗.迪巴拉, 1 <== Total: 1 保罗.迪巴拉可以看出开启延时加载后只打印了一次SQL语句
Mybatis缓存
什么是MyBatis缓存
在一个Web项目中,查询数据库中的操作算是一个非常常用的操作,但是有些数据会被经常性的查询,而每一次都去数据库中查询这些重复的数据,会很消耗数据库的资源,同时使得查询效率也很低,而 MyBatis 中就通过缓存技术来解决这样的问题,也就是说:将一些经常查询,并且不经常改变的,以及数据的正确对最后的结果影响不大的数据,放置在一个缓存容器中,当用户再次查询这些数据的时候,就不必再去数据库中查询,直接在缓存中提取就可以了。
MyBatis 提供了 一级缓存和二级缓存两种形式
- 一级缓存:它是 SqlSession 级别的缓存,SqlSession 类的实例对象中提供了一个 HashMap 的结构,可以用于存储缓存数据,当我们再次查询同一数据的时候,MyBatis 会先去 SqlSession 中查询,有的话,就直接调用
- 二级缓存:是Mapper 级别的缓存,也就是说,如果多个 SqlSession 类的实例,去操作同一个Mapper配置文件中的SQL,这些实例对象可以共用二级缓存
一级缓存
通过一个例子来说:
- 第一次查询 id 为某个值的用户信息时,先去 SqlSesion 的一级缓存中去寻找,如果找到了,就直接用,如果没有找到就去数据库中去查,然后将查到的内容存到一级缓存区域
- 但是,如果在下一次操作中,执行了 commit 操作,也就是执行了增删改的操作,一级缓存区域内的内容会被清空,这是为了保证缓存中的数据的有效性,避免脏读的产生
- 一级缓存是默认开启的。
如何使用
-
创建表
create table user( id int primary key auto_increment, username varchar(11), password varchar(11), age int ); -
创建表对应的实体类
public class User { private long id; private String username; private String password; private int age; ...请补充get、set } -
创建接口
public interface UserIntf { public User findById(long id); } -
创建接口的代理对象
<mapper namespace="com.sheep.repository.UserIntf"> <select id="findById" parameterType="java.lang.Long" resultType="com.sheep.pojo.User"> select * from user3 where id=#{id} </select> </mapper> -
测试
import com.sheep.pojo.User; import com.sheep.repository.UserIntf; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test8 { public static void main(String[] args) { InputStream resourceAsStream = Test8.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream); SqlSession sqlSession = build.openSession(); UserIntf mapper = sqlSession.getMapper(UserIntf.class); User byId = mapper.findById(1L); System.out.println(byId); User byId2 = mapper.findById(1L); System.out.println(byId2); System.out.println(byId.hashCode()); System.out.println(byId2.hashCode()); } }
可以看出虽然查询了两次但是只执行了一次SQL,而且两次返回的内存地址是一致的。
-
当关闭第一次SqlSession时
import com.sheep.pojo.User; import com.sheep.repository.UserIntf; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test8 { public static void main(String[] args) { InputStream resourceAsStream = Test8.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream); SqlSession sqlSession = build.openSession(); UserIntf mapper = sqlSession.getMapper(UserIntf.class); User byId = mapper.findById(1L); System.out.println(byId); System.out.println(byId.hashCode()); //关闭session sqlSession.close(); //从新开启 SqlSession sqlSession1 = build.openSession(); UserIntf mapper1 = sqlSession1.getMapper(UserIntf.class); User byId1 = mapper1.findById(1l); System.out.println(byId1); System.out.println(byId1.hashCode()); sqlSession.close(); } }
当第一次关闭SqlSession后,返回的内存地址不相同,并且执行了两次SQL
二级缓存
一级缓存是基于同一个SqlSession的,但有时候由于方法的封装等原因、或者是在查询完后SqlSession对象会关闭,一级缓存就清空了,导致无法从中获取内容。
二级缓存可以解决一级缓存无法使用的情况,前面已经说过二级缓存是Mapper级别的缓存,多个SqlSession类的实例对象加载同一个Mapper配置文件,并执行其中SQL配置,他们就共享同一个Mapper缓存。
- 查询时,先去Mapper缓存区去找这个值,如果找不到,就去数据库查,然后将查询到的结果存储到缓存中,等下次使用
- 当某个SqlSession类的实例对象执行了增删改操作时,二级缓存就会被清空。
如何使用
-
在config.xml中开启二级缓存
<settings> <!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/> </settings> -
在Mapper映射文件中添加配置
<cache/> -
实体类实现序列化接口
public class User implements Serializable { private long id; private String username; private String password; private int age; } -
测试
import com.sheep.pojo.User; import com.sheep.repository.UserIntf; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class Test8 { public static void main(String[] args) { InputStream resourceAsStream = Test8.class.getClassLoader().getResourceAsStream("config.XML"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream); SqlSession sqlSession = build.openSession(); UserIntf mapper = sqlSession.getMapper(UserIntf.class); User byId = mapper.findById(1L); System.out.println(byId); System.out.println(byId.hashCode()); //关闭session sqlSession.close(); //从新开启 SqlSession sqlSession1 = build.openSession(); UserIntf mapper1 = sqlSession1.getMapper(UserIntf.class); User byId1 = mapper1.findById(1l); System.out.println(byId1); System.out.println(byId1.hashCode()); sqlSession.close(); } }
可以看出第一次查询虽然关闭但是只查询了一次SQL语句,虽然两个对象地址并不相等。
MyBatis逆向工程
逆向工程
MyBatis框架需要:实体类、自定义Mapper接口、Mapper.xml
传统开发中上述的三个组件需要开发者手动创建,逆向工程可以帮助开发者自动创建三个组件,减轻开发者的工作量,提高效率。
如何使用
MyBatis Generator,简称MBG,是一个专门为MyBatis框架开发者定制的代码生成器,可自动生成MyBtais框架所需的实体类,Mapper接口、Mapper.xml,支持基本的CRUD操作。但是相对复杂的SQL需要开发者自己来完成。
-
新建Maven工程,pom.xml
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.22</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.4.0</version> </dependency> </dependencies> <!-- 解决找不到资源文件配置 --> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.XML</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build> -
创建MBG配置文件generatorConfig.xml
- jdbcConnection配置数据库连接信息
- javaModelGenerator配置JavaBean生成策略
- sqlMapGenerator配置SQL映射文件生成策略
- javaClientGenerator配置Mapper接口的生成策略。
- table配置目标数据表(tableName:表名,dmainObjectName:JavaBean类名)。
<?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="testTables" targetRuntime="Mybatis3"> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/user01?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=true" userId="root" password="123321" ></jdbcConnection> <javaModelGenerator targetPackage="com.Sheep.pojo" targetProject="./src/main/java"></javaModelGenerator> <sqlMapGenerator targetPackage="com.Sheep.repository" targetProject="./src/main/java"></sqlMapGenerator> <javaClientGenerator type="XMLMAPPER" targetPackage="com.Sheep.repository" targetProject="./src/main/java"></javaClientGenerator> <table tableName="t_user" domainObjectName="User"></table> </context> </generatorConfiguration><generatorConfiguration> <context id="自定义" targetRuntime="必须Mybatis3"> <jdbcConnection driverClass="驱动" connectionURL="URL" userId="root" password="password" ></jdbcConnection> <javaModelGenerator targetPackage="创建后的实体类存放的包" targetProject="包放的目录下"></javaModelGenerator> <sqlMapGenerator targetPackage="创建后的SQL映射存放的包" targetProject="./src/main/java"></sqlMapGenerator> <javaClientGenerator type="XMLMAPPER" targetPackage="com.Sheep.repository" targetProject="./src/main/java"></javaClientGenerator> <table tableName="要映射的表" domainObjectName="实体类额名字"></table> </context> </generatorConfiguration> -
创建Generator执行的类
package com.Sheep.test; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.exception.InvalidConfigurationException; import org.mybatis.generator.exception.XMLParserException; import org.mybatis.generator.internal.DefaultShellCallback; import java.io.File; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<String> warings = new ArrayList<String>(); boolean overwrite = true; /** *genCig:resources/generatorConfig.xml */ String genCig = "/generatorConfig.xml"; File configfile = new File(Main.class.getResource(genCig).getFile()); ConfigurationParser configurationParser = new ConfigurationParser(warings); Configuration configuration = null; try { configuration = configurationParser.parseConfiguration(configfile); } catch (IOException e) { e.printStackTrace(); } catch (XMLParserException e) { e.printStackTrace(); } DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = null; try { myBatisGenerator=new MyBatisGenerator(configuration,callback,warings); } catch (InvalidConfigurationException e) { e.printStackTrace(); } try { myBatisGenerator.generate(null); } catch (SQLException throwables) { throwables.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } -
运行
浙公网安备 33010602011771号