上一篇博文中介绍的是Mybatis的基本使用,手动加载调用xml中的mapper。本篇介绍一下动态DAO,不需要手动去调用xml中的SQL。
SQL语句配置文件和DAO编写
DAO
public interface UserMapper {
public User findUserById(Integer id);
//动态代理形势中,如果返回结果集问List,那么mybatis会在生成实现类的使用会自动调用selectList方法
public List<User> findUserByUserName(String userName);
public void insertUser(User user);
// 加了@Param xml中的语句使用对象中的参数时,一级参数名也必须加上前缀,例如user.name而不能直接写name
// public void insertUser(@org.apache.ibatis.annotations.Param("user") User user);
public List<User> findUserbyVo(QueryVo vo);
public List<User> findUserByUserNameAndSex(User user);
public List<User> findUserByIds(QueryVo vo);
public List<CustomOrders> findOrdersAndUser1() ;
public List<Orders> findOrdersAndUser2();
public List<User> findUserAndOrders();
}
// 查询VO对象
public class QueryVo {
private User user;
private List<Integer> ids;
...
}
<?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接口代理实现编写规则:
0. 配置文件文件名和DAO文件名要相同,在同一个目录下,方便引用
1. 映射文件中namespace要等于接口的全路径名称
2. 映射文件中sql语句id要等于接口的方法名称:配置文件中的三条SQL语句的id和上面DAO的方法名是相同的
3. 映射文件中传入参数类型要等于接口方法的传入参数类型
4. 映射文件中返回结果集类型要等于接口方法的返回值类型
-->
<mapper namespace="cn.mapper.UserMapper"><!--这里是规则1,namespace要等于接口的全路径名称-->
<!--
id:sql语句唯一标识
parameterType:指定传入参数类型
resultType:返回结果集类型
#{}占位符:起到占位作用,如果传入的是基本类型(string,long,double,int,boolean,float等),那么#{}中的变量名称可以随意写.
-->
<select id="findUserById" parameterType="int" resultType="cn.pojo.User">
select * from user where id=#{id}
</select>
<!--
如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所以映射文件中应该配置成集合泛型的类型
${}拼接符:字符串原样拼接,如果传入的参数是基本类型(string,long,double,int,boolean,float等),那么${}中的变量名称必须是value
注意:拼接符有sql注入的风险,所以慎重使用
-->
<select id="findUserByUserName" parameterType="string" resultType="user"><!--注意这里,需要核心配置文件配合配置,一般我们直接写类的全路径即可-->
select * from user where username like '%${value}%'
</select>
<!--
#{}:如果传入的是pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性.....
如果要返回数据库自增主键:可以使用select LAST_INSERT_ID()
-->
<insert id="insertUser" parameterType="cn.pojo.User" >
<!-- 执行 select LAST_INSERT_ID()数据库函数,返回自增的主键
keyProperty:将返回的主键放入传入参数的Id中保存.
order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是AFTER
resultType:id的类型,也就是keyproperties中属性的类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
<select id="findUserbyVo" parameterType="cn.pojo.QueryVo" resultType="cn.pojo.User">
select * from user where username like '%${user.username}%' and sex=#{user.sex}
</select>
<!-- 封装sql条件,封装后可以重用.
id:是这个sql条件的唯一标识 -->
<sql id="user_Where">
<!-- where标签作用:
会自动向sql语句中添加where关键字
会去掉第一个条件的and关键字
-->
<where>
<if test="username != null and username != ''">
and username like '%${username}%'
</if>
<if test="sex != null and sex != ''">
and sex=#{sex}
</if>
</where>
</sql>
<select id="findUserByUserNameAndSex" parameterType="cn.pojo.User" resultType="cn.pojo.User">
select * from user
<!-- 调用sql条件 -->
<include refid="user_Where"></include>
</select>
<select id="findUserByIds" parameterType="cn.pojo.QueryVo" resultType="cn.pojo.User">
select * from 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>
<!-- 一对一:自动映射 -->
<select id="findOrdersAndUser1" resultType="cn.pojo.CustomOrders"><!--创建一个CustomOrders类,里面的属性和联合查询出来的字段一一对应即可-->
select a.*, b.id uid, username, birthday, sex, address
from orders a, user b
where a.user_id = b.id
</select>
<!-- 一对一:手动映射 -->
<!--
id:resultMap的唯一标识
type:将查询出的数据放入这个指定的对象中
注意:手动映射需要指定数据库中表的字段名与java中pojo类的属性名称的对应关系
Orders类中的属性可以是基本类型和类的组合,例如有个User类型的属性
-->
<resultMap type="cn.pojo.Orders" id="orderAndUserResultMap">
<!-- id标签指定主键字段对应关系
column:列,数据库中的字段名称
property:属性,java中pojo中的属性名称
-->
<id column="id" property="id"/>
<!-- result:标签指定非主键字段的对应关系 -->
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 这个标签指定单个对象的对应关系
property:指定将数据放入Orders中的user属性中
javaType:user属性的类型
-->
<association property="user" javaType="cn.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="orderAndUserResultMap">
select a.*, b.id, b.uid, b.username, b.birthday, b.sex, b.address
from orders a, user b
where a.user_id = b.id
</select>
<resultMap type="cn.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属性的泛型类型
注意这里!!!!集合中的主键字段名字不能喝user对象中的主键相同,例如都叫id,则会只能查出来1条
-->
<collection property="ordersList" ofType="cn.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="findUserAndOrders" resultMap="userAndOrdersResultMap">
select a.*, b.id oid ,user_id, number, createtime
from user a, orders b where a.id = b.user_id
</select>
</mapper>
补充,如果参数是map,如何遍历?
<select id="queryAdSlotKVByCondition" resultType="com.dhgate.ssp.des.entity.db.AdSlotKVSetting" parameterType="java.util.Map">
SELECT * FROM
dh_ssp.adslotkvsetting
<if test="condition != null">
WHERE
<foreach collection="condition.keys" separator=" and " item="key">
${key}=#{condition[${key}]}
</foreach>
</if>
</select>
foreach循环中会拼接成key1=value1 and key2=value2...这种形式
核心配置文件
db.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=admin
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>
<properties resource="db.properties"></properties>
<typeAliases>
<!-- 定义单个pojo类别名,例如上面SQL语句配置文件中使用的User类
type:类的全路劲名称
alias:别名
-->
<!-- <typeAlias type="cn.pojo.User" alias="user"/> -->
<!-- 使用包扫描的方式批量定义别名
定以后别名等于类名,不区分大小写,但是建议按照java命名规则来,首字母小写,以后每个单词的首字母大写
-->
<package name="cn.pojo"/>
</typeAliases>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="User.xml"/>
<!--
使用class属性引入接口的全路径名称:
使用规则:
1. 接口的名称和映射文件名称除扩展名外要完全相同
2. 接口和映射文件要放在同一个目录下
-->
<!-- <mapper class="cn.mapper.UserMapper"/> -->
<!-- 使用包扫描的方式批量引入Mapper接口
使用规则:
1. 接口的名称和映射文件名称除扩展名外要完全相同
2. 接口和映射文件要放在同一个目录下
-->
<package name="cn.mapper"/>
</mappers>
</configuration>
代码调用
public class UserMapperTest {
private SqlSessionFactory factory;
//作用:在测试方法前执行这个方法
@Before
public void setUp() throws Exception{
String resource = "SqlMapConfig.xml";
//通过流将核心配置文件读取进来
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过核心配置文件输入流来创建会话工厂
factory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
User user = mapper.findUserById(1);
System.out.println(user);
}
@Test
public void testFindUserByUserName() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<User> list = mapper.findUserByUserName("王");
System.out.println(list);
}
@Test
public void testInsertUser() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("老王");
user.setSex("1");
user.setBirthday(new Date());
user.setAddress("北京昌平");
mapper.insertUser(user);
openSession.commit();
}
@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);
List<User> list = mapper.findUserbyVo(vo);
System.out.println(list);
}
@Test
public void testFindUserbyUserNameAndSex() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
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);
}
@Test
public void testFindUserbyIds() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
QueryVo vo = new QueryVo();
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(16);
ids.add(28);
ids.add(22);
vo.setIds(ids);
List<User> list = mapper.findUserByIds(vo);
System.out.println(list);
}
@Test
public void testFindOrdersAndUser() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<CustomOrders> list = mapper.findOrdersAndUser1();
System.out.println(list);
}
@Test
public void testFindOrdersAnduUser2() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<Orders> list = mapper.findOrdersAndUser2();
System.out.println(list);
}
@Test
public void testFindUserAndOrders() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<User> list = mapper.findUserAndOrders();
System.out.println(list);
}
}