一、输入映射和输出映射
1.1 输入参数映射
1.1.1 传递简单类型
上一节演示过了
1.1.2 传递pojo对象
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
1.1.3 传递pojo包装对象
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo类中包含pojo。
需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
在UserMapp.xml中添加:
<select id="findUserByVo" parameterType="com.ken.pojo.QueryVo" resultType="com.ken.pojo.User">
select * from user where username like '%${user.username}%' and sex=#{user.sex}
</select>
UserMapper接口中添加方法声明:
List<User> findUserByVo(QueryVo vo);
UserMapperTest中添加:
@Test
public void testFindUserByVo() throws Exception {
SqlSession openSession = factory.openSession();
// 通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("王");
user.setSex("1");
vo.setUser(user);
mapper.findUserByVo(vo);
openSession.commit();
}
1.2 返回值映射
1.2.1 输出简单类型
UserMapper.xml
<select id="findUserCount" resultType="java.lang.Integer">
select count(*) from user
</select>
UserMapper
Integer findUserCount();
UserMapperTest
@Test
public void testFindUserCount() throws Exception {
SqlSession openSession = factory.openSession();
UserMapper mapper = openSession.getMapper(UserMapper.class);
Integer count = mapper.findUserCount();
System.out.println("========" + count);
openSession.commit();
}
只有返回结果为一行一列的时候,那么返回值类型才可以指定成基本类
1.2.2 输出pojo对象
参考上一节内容
1.2.3 输出pojo列表
参考上一节内容
1.3 resultMap
略
二、动态sql
2.1 If
UserMapper.xml
<select id="findUserByUserNameAndSex" parameterType="user" resultType="user">
select * from user where 1=1
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</select>
UserMapper
List<User> findUserByUserNameAndSex(User user);
UserMapperTest
@Test
public void testFindUserByUserNameAndSex() throws Exception {
SqlSession openSession = factory.openSession();
UserMapper mapper = openSession.getMapper(UserMapper.class);
User user = new User();
// user.setUsername("王");
user.setSex("1");
List<User> list = mapper.findUserByUserNameAndSex(user);
System.out.println(list);
openSession.commit();
}
2.2 Where
我们可以对上面这个例子的配置文件用where进行修改
<select id="findUserByUserNameAndSex" parameterType="user"
resultType="user">
select * from user
<!--
where标签作用:
会自动向sql语句中添加where关键字
会去掉第一个条件的and关键字
-->
<where>
<if test="username!=null and username!=''">
username like '%${username}%'
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</where>
</select>
我们还可以把where里面的片段提取出来,以便复用。
2.3 Foreach
我们要实现一个查询:
select * from user where id in (1, 10, 28, 33)
UserMapper.xml
<select id="findUserByIds" parameterType="queryVo" resultType="user" >
select * from user
<where>
<if test="ids != null">
<!--
foreach:循环传入的集合参数。
collection:传入的集合的变量名称。
item:每次循环将循环出的数据放入这个变量中,这里可以随便取名。用于下方占位符里。
open:循环开始拼接的字符串;】。
close:循环结束拼接的字符串。
separator:循环中拼接的分隔符。
-->
<foreach collection="ids" item="id" open="id in (" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
UserMapper:
List<User> findUserByIds(QueryVo vo);
测试:
@Test
public void testFindUserByIds() throws Exception {
SqlSession openSession = factory.openSession();
UserMapper mapper = openSession.getMapper(UserMapper.class);
QueryVo vo = new QueryVo();
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(10);
ids.add(16);
ids.add(28);
vo.setIds(ids);
List<User> list = mapper.findUserByIds(vo);
System.out.println(list);
openSession.commit();
}
2.4 Sql片段
三、关联查询
3.1 一对一关联
一对一:自动映射
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
private User user;
}
public class CustomOrders extends Orders {
private int uid;
private String username;
private String sex;
private Date birthday;
private String address;
//getter and setter
}
UserMapper.xml
<!-- 一对一:自动映射 -->
<select id="findOrdersAndUser1" resultType="com.ken.pojo.CustomOrders">
select a.*, b.id uid, username, birthday, sex, address from orders a, user b where a.user_id = b.id
</select>
UserMapper
List<CustomOrders> findOrdersAndUser1();
测试:
@Test
public void testFindOrderAndUser() throws Exception {
SqlSession openSession = factory.openSession();
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<CustomOrders> list = mapper.findOrdersAndUser1();
System.out.println(list);
openSession.commit();
}
一对一:手动映射(mybatis标准的方式)
UserMapper.xml
<!-- 一对一:手动映射 -->
<!--
id:resultMap的唯一标识
type:将查询出的数据放入这个指定的对象中
注意:手动映射需要指定数据库中标的字段名域java中pojo类的属性名称的对应关系
-->
<resultMap type="com.ken.pojo.Orders" id="ordersAndUserResultMap">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!--
association:指定单个对象的对应关系
property:指定将数据放入Orders中的user属性中
javaType:user属性的类型
-->
<association property="user" javaType="com.ken.pojo.User">
<id column="uid" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="findOrdersAndUser2" resultMap="ordersAndUserResultMap">
select a.*, b.id uid, username, birthday, sex, address from orders a, user b
where a.user_id = b.id
</select>
UserMapper
List<Orders> findOrdersAndUser2();
测试:
@Test
public void testFindOrderAndUser2() throws Exception {
SqlSession openSession = factory.openSession();
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<Orders> list = mapper.findOrdersAndUser2();
System.out.println(list);
openSession.commit();
}
3.2 一对多关联
public class User implements Serializable {
private int id;
private String username;
private String sex;
private Date birthday;
private String address;
private List<Orders> ordersList;
//getter and setter
}
UserMapper.xml
<resultMap type="com.ken.pojo.User" id="userAndOrdersResultMap">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!--
指定对应的集合关系映射
property:将数据放入User对象中的ordersList属性中
ofType:指定ordersList属性的泛型类型
-->
<collection property="ordersList" ofType="com.ken.pojo.Orders">
<id column="oid" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
</collection>
</resultMap>
<select id="findeUserAndOrders" resultMap="userAndOrdersResultMap">
select a.*, b.id oid, user_id, number, createtime from user a, orders b where a.id = b.user_id
</select>
UserMapper
List<User> findeUserAndOrders();
测试:
@Test
public void testFindeUserAndOrders() throws Exception {
SqlSession openSession = factory.openSession();
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<User> list = mapper.findeUserAndOrders();
System.out.println(list);
openSession.commit();
}
四、Mybatis整合spring
凡是spring的配置文件中,要引入其他的配置文件,都要加classpath。如果不是spring的配置文件,就不要加classpath。
4.1 spring整合原生dao的方式
整合思路:
1、SqlSessionFactory对象应该放到spring容器中作为单例存在。
2、传统dao的开发方式中,应该从spring容器中获得sqlsession对象。3、Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
4、数据库的连接以及数据库连接池事务管理都交给spring容器来完成。
5.2整合需要的jar包
1、spring的jar包
2、Mybatis的jar包
3、Spring+mybatis的整合包。
4、Mysql的数据库驱动jar包。
5、数据库连接池的jar包。
5.3整合的步骤
第一步:创建一个java工程。
第二步:导入jar包。(上面提到的jar包)
第三步:mybatis的配置文件sqlmapConfig.xml
第四步:编写Spring的配置文件
1、数据库连接及连接池
2、事务管理(暂时可以不配置)
3、sqlsessionFactory对象,配置到spring容器中
4、mapeer代理对象或者是dao实现类配置到spring容器中。
第五步:编写dao或者mapper文件
第六步:测试。
5.3.1SqlMapConfig.xml
5.3.2applicationContext.xml
5.3.3db.properties
5.4Dao的开发
三种dao的实现方式:
1、传统dao的开发方式
2、使用mapper代理形式开发方式
3、使用扫描包配置mapper代理。
5.4.1传统dao的开发方式
接口+实现类来完成。需要dao实现类需要继承SqlsessionDaoSupport类
5.4.1.1 Dao实现类
5.4.1.2 配置dao
4.2 spring整合mapper的方式
applicationContext.xml
<!-- Mapper接口代理实现 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 配置mapper接口的全路径名称 -->
<property name="mapperInterface" value="com.ken.mapper.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
UserMapperTest
private ApplicationContext applicationContext;
@Before
public void setUp(){
applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
}
@Test
public void testFindUserById(){
UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
User user = userMapper.findUserById(1);
System.out.println(user);
}
}
4.3 批量导入mapper
applicationContext.xml
<!--
使用包扫描的方式批量导入mapper
扫描后引用的时候可以使用类名,首字母小写
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定要扫描的包的全路径名称。如果有多个包,用应为状态下的逗号分隔 -->
<property name="basePackage" value="com.ken.mapper"/>
</bean>
UserMapperTest
@Test
public void testFindUserById() {
UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");//扫描后引用的时候可以使用类名,首字母小写
User user = userMapper.findUserById(1);
System.out.println(user);
}
五、逆向工程
使用官方网站的mapper自动生成工具mybatis-generator-core-1.3.2来生成po类和mapper映射文件。
作用:mybatis官方提供逆向工程,可以使用它通过数据库中的表来自动生成Mapper接口和映射文件(单表增删改查)和Po类.
可以根据表结构自动的生成po类,还可以生成单表的mapper。
5.1 创建mybatis_generator java工程
5.2 导包:
1.这个工程是mybatis的逆向工程,所以要导入mybatis的核心包
2.根据数据库中的表生成po类,所以要连接数据,需要数据库驱动包
3.mybatis逆向工程的jar包
5.3 在工程下创建generator.xml
generator.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>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL
和 NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.ken.pojo"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.ken.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.ken.mapper" targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table tableName="orders"></table>
<table tableName="user"></table>
<!-- 有些表的字段需要指定java类型 <table schema="" tableName=""> <columnOverride column=""
javaType="" /> </table> -->
</context>
</generatorConfiguration>
5.4 调用类
public class StartServer {
public void generator() throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("generator.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 {
StartServer startServer = new StartServer();
startServer.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.5 运行->刷新
注意:mybatis逆向工程的生成的代码是追加形式的。如果,重复运行了逆向工程,我们打开类,没问题,但是文件的大小变了。再用这些文件,就没法用。所以,要重新运行,就要把原来生成的文件全部删除。
5.6 使用
将刚刚生成的的mapper和po拷贝到我们之前的工程mybatis_spring对应的包下(把之前包里的文件删除)。
UserMapperTest
@Test
public void testFindUserById() {
UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
User user = userMapper.selectByPrimaryKey(1);
System.out.println(user);
}
@Test
public void testFindUserAndSex() {
UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
// 创建UserExample对象
UserExample userExample = new UserExample();
// 通过UserExample对象创建查询条件封装对象(Criteria中是封装的查询条件)
Criteria criteria = userExample.createCriteria();
criteria.andUsernameLike("%王%");
criteria.andSexEqualTo("1");
List<User> list = userMapper.selectByExample(userExample);
System.out.println(list);
}