Mybatis
Mybatis映射文件
MyBatis 的真正强大在于它的映射语句,映射器的 XML 文件相对简单。如果拿它跟JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
cache – 给定命名空间的缓存配置。
cache-ref – 其他命名空间缓存配置的引用。
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
sql – 可被其他语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语句
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
select
select 元素有很多属性允许你配置,来决定每条语句的作用细节。
insert, update 和 delete
insert详解
插入语句的配置规则非常丰富,在插入语句里面有一些额外的属性和子元素用来处理主键的生成,而且有多种生成方式,我们来详细说明一下。
1.首先,如果你的数据库支持自动生成主键的字段,那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就OK。这样当我们插入之后,我们的对象会自动设置数据库返回的主键。
<insert id="insertUser" parameterType="com.cad.domain.User" useGeneratedKeys="true" keyProperty="id">
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
- 1
- 2
- 3
- 4
- 5
2.如果你的数据库还支持多行插入, 你也可以传入一个Authors数组或集合,并返回自动生成的主键。
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username, password, email, bio) values
<foreach item="item" collection="AuthorList" separator=",">
(#{item.username}, #{item.password}, #{item.email}, #{item.bio})
</foreach>
</insert>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
sql
这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化.
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
parameterType(输入类型)
我们传入的参数可以是简单数据类型,或者对象,前一天我们已经演示过,这里有一个点需要注意。
默认情况下,使用#{}格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值。这样做更安全,更迅速,通常也是首选做法,不过有时你只是想直接在 SQL 语句中插入一个不改变的字符串。比如,:ORDER BY ${columnName}。这里 MyBatis 不会修改或转义字符串。以这种方式接受从用户输出的内容并提供给语句中不变的字符串是不安全的,会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。
resultMap
resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
例如:当我们使用resultType时
<select id="selectUsers" resultType="User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
其实MyBatis会自动创建一个 ResultMap,基于数据库属性名来映射列到 JavaBean 的属性上,所以必须得保证数据库字段名和JavaBean属性一致。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
如果列名没有精确匹配,你可以在列名上使用 select 字句的别名(一个 基本的 SQL 特性)来匹配属性。
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
但是,Mybatis给我们提供了简便强大的resultMap
例如,我们的实体类user_sex和数据库字段sex不匹配
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String username;// 用户姓名
private String user_sex;// 性别
private Date birthday;// 生日
private String address;// 地址
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
<!--type为返回类型-->
<resultMap type="com.cad.domain.User" id="userResultMap">
<!--property为属性,column为对应的数据库字段,这样再查询就能匹配上-->
<result property="user_sex" column="sex" />
</resultMap>
<select id="findUserById" parameterType="int" resultMap="userResultMap">
select * from user where id =#{id}
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
缓存
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行
<cache/>
- 1
这个简单的一行有如下的功能:
- 映射语句文件中的所有 select 语句将会被缓存。
- 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
- 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
- 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
- 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
- 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
缓存有一些属性:
eviction:收回策略,四个值:LRU ,FIFO,SOFT ,WEAK
lushInterval(刷新间隔):可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目):可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。默认值是 1024。
readOnly(只读):属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。
Mybatis还可以自定义缓存,可以自行去参考文档。
动态sql
MyBatis 的强大特性之一便是它的动态 SQL。我们使用JDBC时会手动拼接条件,Mybatis解决了这一情况。
if标签
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。
<!--根据id和姓名查找用户-->
<select id="findUserByIdAndUsername" parameterType="com.cad.domain.User" resultType="com.cad.domain.User">
select * from user
where 1=1
<if test="id !=null and id!=''">
and id=#{id}
</if>
<if test="username !=null and username !=''">
and username =#{username}
</if>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
public class MybatisTest {
@Test
public void test() throws IOException {
String resource="config/sqlMapConfig.xml";
InputStream in=Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
SqlSession sqlSession=factory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setId(10);
user.setUsername("张三");
List<User> list=userMapper.findUserByIdAndUsername(user);
for(User u:list) {
System.out.println(u);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
choose, when, otherwise标签
有些时候,我们不想用到所有的条件语句,而只想从中选择。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
例如:提供了“id”就按“id”查找,提供了“username”就按“username”查找,若两者都没有提供,就按照otherwise里面的条件查找*。其实是蛮鸡肋的一功能。
<!-- 根据id和名字查找用户 -->
<select id="findUserByIdAndUsername" parameterType="com.cad.domain.User" resultType="com.cad.domain.User">
select * from user
where 1=1
<choose>
<when test="id != null">
AND id = #{id}
</when>
<when test="username != null and username !=''">
AND username = #{username}
</when>
<otherwise>
AND sex = 1
</otherwise>
</choose>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
where标签
上面的例子我们都需要写where 1=1,因为如果不写,条件拼接就会出现很多错误,Mybatis通过where标签帮我们解决了这个问题。
<select id="findUserByIdAndUsername" parameterType="com.cad.domain.User" resultType="com.cad.domain.User">
select * from user
<where>
<if test="id != null">
AND id = #{id}
</if>
<if test="username != null and username !=''">
AND username = #{username}
</if>
</where>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
foreach标签
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
//创建一个对象,封装一个ids
public class QueryVo {
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
<!-- 根据多个id查找用户信息 -->
<select id="findUserByIds" parameterType="com.cad.domain.QueryVo" resultType="com.cad.domain.User">
select * from user
where id in
<!--如果集合是对象封装起来的,可以直接使用属性名字。-->
<foreach collection="ids" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
public class MybatisTest {
@Test
public void test() throws IOException {
String resource="config/sqlMapConfig.xml";
InputStream in=Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
SqlSession sqlSession=factory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<Integer> l=new ArrayList<Integer>();
l.add(10);
l.add(16);
l.add(22);
QueryVo queryVo=new QueryVo();
queryVo.setIds(l);
List<User> list=userMapper.findUserByIds(queryVo);
for(User u:list) {
System.out.println(u);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
如果我们的list在某个对象内部,那么foreach时,collection可以直接使用list名字。如果我们直接new了一个数组或者list集合,collection属性必须使用array或者list,这样才能遍历到。
关联查询
前面我们讲了将简单的数据映射到对象中,可惜实际工作中的任务不总是这么简单,往往多个对象之间存在着各种关联关系,我们来看看使用Mybatis怎么处理。我们还是需要使用到resultMap
一对一映射
1.我们创建Order表与User表关联
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '下单用户id',
`number` varchar(32) NOT NULL COMMENT '订单号',
`createtime` datetime NOT NULL COMMENT '创建订单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `FK_orders_1` (`user_id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ;
INSERT INTO `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `orders` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
2.创建对应的实体类
public class Orders implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number == null ? null : number.trim();
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note == null ? null : note.trim();
}
}
- 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
- 64
- 65
- 66
- 67
- 68
3.编写映射文件
<mapper namespace="com.cad.domain.OrdersMapper">
<resultMap type="com.cad.domain.Orders" id="orders">
<!--只会映射指定的字段,其他未显式指定的都为null-->
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="number" column="number"/>
<!--用association表示关联的对象,property为属性名,javaType为类型-->
<association property="user" javaType="com.cad.domain.User">
<id column="user_id" property="id"/>
<result property="username" column="username"/>
</association>
</resultMap>
<select id="findOrders" resultMap="orders">
SELECT * FROM orders LEFT JOIN USER ON orders.user_id=user.id
</select>
</mapper>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
4.编写Mapper接口,将映射文件添加到核心配置文件中,然后测试
public class MybatisTest {
@Test
public void test() throws IOException {
String resource="config/sqlMapConfig.xml";
InputStream in=Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
SqlSession sqlSession=factory.openSession();
OrdersMapper mapper=sqlSession.getMapper(OrdersMapper.class);
List<Orders> list=mapper.findOrders();
for(Orders o:list) {
System.out.println("order:"+o.toString());
System.out.println("user:"+o.getUser().toString());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
一对多关联
1.我们在user实体类中添加orders字段
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
private List<Orders> orders;
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", sex=" + sex
+ ", birthday=" + birthday + ", address=" + address + ",orders"+orders+"]";
}
}
- 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
2.配置映射文件
<resultMap type="com.cad.domain.User" id="users">
<id property="id" column="id"/>
<result property="username" column="username"/>
<!--这里使用ofType指定集合内部存储对象的类型-->
<collection property="orders" ofType="com.cad.domain.Orders">
<id column="oid" property="id"/>
<result property="number" column="number"/>
</collection>
</resultMap>
<select id="findUserOrders" resultMap="users">
SELECT u.*,o.id oid,o.number FROM user u LEFT JOIN orders o ON o.user_id=u.id
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3.将方法添加到mapper接口中,我们测试一下
public class MybatisTest {
@Test
public void test() throws IOException {
String resource="config/sqlMapConfig.xml";
InputStream in=Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder= new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
SqlSession sqlSession=factory.openSession();
OrdersMapper mapper=sqlSession.getMapper(OrdersMapper.class);
List<User> list=mapper.findUserOrders();
for(User u:list) {
System.out.println("user:"+u.toString());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
Mybatis整合Spring
1.创建空项目,导入jar包 ,mybtias-spring.jar很重要,可以去maven下载
- 1
- 2
2.创建SqlMapConfig.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>
<mappers>
<!--映射该包下的所有映射文件-->
<package name="com.cad.mapper"/>
</mappers>
</configuration>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
3.创建Mapper接口和Mapper映射文件
public interface UserMapper {
public List<User> findUsers();
}
- 1
- 2
- 3
- 4
- 5
- 6
<?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.cad.mapper.UserMapper">
<select id="findUsers" resultType="com.cad.domain.User">
select * from user
</select>
</mapper>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
4.创建Spring配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 配置数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 配置sqlSession工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置接口,帮我们生成代理实现类 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!--传入工厂和接口-->
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
<property name="mapperInterface" value="com.cad.mapper.UserMapper"></property>
</bean>
</beans>
- 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
5.测试一下
public class TestDemo {
@Test
public void test() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//获取接口实现类
UserMapper mapper=(UserMapper)applicationContext.getBean("userMapper");
List<User> list=mapper.findUsers();
for(User user:list) {
System.out.println(user.toString());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
上面的整合看似简便了不少,但是有一个严重的问题。我们每多一个Mapper接口,就得需要在Spring配置文件中多加一个配置,这是一个很繁琐并且工作量很大的工作,Mybatis为我们提供了一个扫描包的功能,可以直接将该包下的接口创建实现类。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 配置数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 配置sqlSession工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置扫描方式,创建代理类,不用配置id,每个代理类的id就是接口名,首字母小写-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--配置包-->
<property name="basePackage" value="com.cad.mapper"/>
</bean>
</beans>
- 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
Mybatis逆向工程
我们实际开发中,动辄上百张表,如果一一地去编写对应的pojo和mapper文件,简直是噩梦。Mybatis为我们提供了一个逆向工程,可以根据单表自动生成mybatis执行所需要的(mapper.Java,mapper.xml、po..)等,免去我们不少麻烦,我们来学习一下怎么使用。
官方逆向工程开发文档
http://www.mybatis.org/generator/configreference/xmlconfig.html
- 1
- 2
1.创建新工程,导入jar包,需要mybatis.jar、mysql驱动和mybatis-generator-core.jar
- 1
- 2
- 3
2.创建配置文件 genreatorConfig.xml
<?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">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root"
password="123456">
</jdbcConnection>
<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
userId="yycg"
password="yycg">
</jdbcConnection> -->
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="cn.cad.domain"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="cn.cad.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="cn.cad.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table schema="" tableName="user"></table>
<table schema="" tableName="orders"></table>
<!-- 有些表的字段需要指定java类型
<table schema="" tableName="">
<columnOverride column="" javaType="" />
</table> -->
</context>
</generatorConfiguration>
- 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
3.使用java程序加载配置文件生成我们需要的代码 ,这段java程序在官方文档里面有,直接复制过来即可
public class GeneratorSqlmap {
public void generator() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File("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);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 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
4.生成的Mapper接口中有很多常用的方法,并且我们发现除了生成POJO类,还生成了Example类,这个类是用来加条件的,如查询条件等。
我们来演示一下。
- 1
- 2
public class TestDemo {
@Test
public void test() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserMapper mapper=(UserMapper)applicationContext.getBean("userMapper");
UserExample example=new UserExample();
//添加性别为1的条件
example.createCriteria().andSexEqualTo("1");
int count=(int) mapper.countByExample(example);
System.out.println(count);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-778f64ae39.css" rel="stylesheet">
</div>