Java51Mybatis:两个xml文件的标签,动态sql的if/choose/where/set/foreach标签
Posted 码农编程录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java51Mybatis:两个xml文件的标签,动态sql的if/choose/where/set/foreach标签相关的知识,希望对你有一定的参考价值。
文章目录
1.mybatis-config.xml核心配置文件中标签:test -> interface/impl -> sql
//jdbc.properties文件,如下前面加上jdbc.是防止如上 ${}字符串拼接 拿到下面参数,没有拿到方法中参数
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
//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>
<!--
1.将jdbc.properties配置文件加载到mybatis的环境中。
2.通过${key}读取配置文件中的配置信息
properties声明属性的2种方式:1.resource:相对路径引入外部的properties配置文件
2.property子标签来动态声明
-->
<properties resource="jdbc.properties"> <!--在下面第二个environment标签里用到-->
<!--<property name="username" value="root"></property>--> <!--这行也可以,不用外部 jdbc.properties文件,优先级最低-->
</properties>
<!--111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
<settings>
<!--
开启驼峰映射
经典的映射规范 : 数据库列名 A_COLUMN ————> 属性名 aColumn
-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
<typeAliases> <!--类型别名:如下两种方式:这样UserMapper.xml中resultType="User"就行-->
<!-- 第一种配置方式:typeAlias标签配置单个别名 -->
<!--<typeAlias type="com.itheima.domain.User" alias="User"></typeAlias>-->
<!-- 第二种配置方式:常用,包扫描 ,默认类名就是别名-->
<package name="com.itheima.domain"></package>
</typeAliases>
<!--111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
<!-- 数据源环境:下一行default: 默认采用的环境即数据源配置的环境的id。-->
<environments default="development">
<!-- 配置单个数据源环境,id是当前环境配置的唯一标识。dist生产环境 -->
<environment id="development">
<!--
如下事务管理: type: JDBC or MANAGED
JDBC: 采用jdbc的事务管理。 底层connection.commit/.rollback
MANAGED: 不采用事务。
-->
<transactionManager type="JDBC"/> <!--采用事务-->
<!--
如下配置数据源的具体链接参数:
type: POOLED: 支持连接池配置,除了最基本的数据源连接参数配置,
还可以配置连接池相关的参数如:最大连接数,最大空闲连接数...
UNPOOLED: 不支持连接池配置。
-->
<dataSource type="POOLED"> <!--#{}被动传,${}主动取/拼接-->
<property name="driver" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<!--111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driverClass}"/>
<property name="url" value="${url}"/>
<property name="username" value="aaa"/>
<property name="password" value="bbb"/>
</dataSource>
</environment>
</environments>
<!--111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
<mappers> <!--告知mybatis映射文件的位置,一般一个接口对应一个xxxMapper映射文件-->
<!-- 第一种配置: 相对路径配置映射文件的位置 -->
<!--<mapper resource="UserMapper.xml"/>-->
<!-- 第二种配置:url绝对路径方式,肯定不用 -->
<!-- <mapper url="file:///var/mappers/AuthorMapper.xml"/>-->
<!-- 第三种配置:采用接口的全路径配置方式
此处注意:虽然配置的是类的全路径,但是我们都知道,io流读取资源的本质都是需要知道
文件的名字和位置。
所以: 我们需要通过接口的全路径 com.itheima.mapper.UserMapper
能够知道接口对应的映射文件的 位置 和 名字。
文件的位置和名字必须得满足2个规范: 1.mapper文件名 必须和 接口的名字 一致。
2.mapper文件 必须和 接口 放在同一个包下。
所以将UserMapper.xml和UserMapper.java文件放在com.itheima.mapper文件夹下
-->
<!-- <mapper class="com.itheima.mapper.UserMapper"></mapper>-->
<!-- 第四种配置:包扫描方式 ,基于第三种的规范。-->
<!-- <package name="com.itheima.mapper"></package>-->
<!--要么第一种,要么第四种,如下第一种-->
<mapper resource="com/itheima/mapper/UserMapper.xml"></mapper>
<mapper resource="com/itheima/mapper/commonSql.xml"></mapper> <!--不要忘了引入-->
</mappers>
</configuration>
2.UserMapper.xml映射文件中增删改查标签:动态代理规定namespace,id
mybatis-config.xml中< typeAliases > 和< mappers > 规定resultType和文件名。
2.1 UserMapper.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.itheima.mapper.UserMapper">
<!--
select: 查询的statement(声明),用来编写查询语句
id: 语句的唯一标识
resultType:配置返回的结果集类型
parameterType:传递的参数类型,可以省略
-->
<select id="findUserById" resultType="User">
select * from tb_user where id = #{a}
</select>
<!--
useGeneratedKeys=true, 开启主键的自动回显。(主键必须是自增长的)
keyProperty="id" 主键属性值回显到的实体的属性名 //user对象的id属性
keyColumn="id" 主键的列名
-->
<insert id="addUser" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into tb_user(user_name,password,name) values(#{userName},#{password},#{name})
</insert>
<!--
#{} : 预编译的传参方式
1.如果传递 单个 基本类型参数,sql语句中的参数名可以是任意名称,如上findUserById中#{a}
2.如果传递的是多个基本类型参数
a. #{arg0} #{arg1} 或者 #{param1} #{param2} 获取方法传递的参数(不推荐)
b. 注解方式(推荐),在方法的参数上使用@Param(参数名),
在sql语句中 #{参数名} 来引入方法调用时传递的参数,两参数名要一样。
3.对象类型的参数:#{property} property就是对象的属性名。
4.Hash类型的参数:#{key} key就是map集合中的key。
${} : 字符串拼接方式,语法格式和获取properties配置中的参数语法一致,所以加jdbc.区分。
#{} 预编译方式,参数在传递时,如果是字符串,会自动添加''
${} 字符串拼接方式,只是字符串的拼接。预编译可预防sql注入,但是传的参数是sql语句关键字就不行了。
-->
<select id="findUserByPasswordAndSex" resultType="User">
select * from tb_user where password=#{p} and sex=#{sex}
</select>
<select id="findUserByUsername" resultType="User">
select * from tb_user where user_name = #{username}
</select>
<select id="findUserByHash" resultType="User">
select * from tb_user where password=#{password} and sex=#{sex}
</select>
<select id="findUserByTable" resultType="User">
select * from ${tableName}
</select>
<select id="findUserLikeUsername" resultType="User">
select * from tb_user where user_name like #{username}
</select>
<!--1111111111111111111111111111111111111111111111111111111111111111111111111111111-->
<select id="findUsersBySex" resultMap="myResultMap">
<!-- 自定义结果集映射:resultMap: 自定义结果集的id -->
select <include refid="commonSql.mySql"></include> from tb_user where sex = #{sex}
</select>
<!--
id:自定义结果集的唯一标识
type: 类型。实体的类型,支持别名写法
autoMapping="true" 自动映射,
默认值为true,那么会将列名和属性名一致的进行自动映射。
值为false,只会将我们配置的列进行映射,没有配置的列不进行映射
-->
<resultMap id="myResultMap" type="User" autoMapping="false">
<!--
配置主键和属性的映射的
column:主键的列名
property:实体的属性名
-->
<id column="uid" property="id"></id>
<!-- 如下配置非主键的列的映射的 -->
<result column="user_name" property="userName"></result>
<result column="uage" property="age"></result>
</resultMap>
<!--11111111111111111111111111111111111111111111111111111111111111111111111111111111-->
<!--
sql片段:类似抽成函数方法,反复调用
1.通过<sql>标签来声明一段通用sql
2.在执行sql时,通过<include refid="namespace.sqlId">来引入声明好的sql
如下<include refid="mySql"></include>就行
-->
<sql id="mySql">
*,age uage,id uid
</sql>
<select id="findUsersByAge" resultType="User">
select * from tb_user where age <![CDATA[ < ]]> #{age}
<!-- select * from tb_user where age < #{age} -->
</select>
</mapper>
//commonSql.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="commonSql">
<sql id="mySql">
*,age uage,id uid
</sql>
</mapper>
2.2 mapper
生成订单详情需要订单的标识id,插入数据库才有id,这个id也只存在数据库中。
package com.itheima.mapper;
import com.itheima.domain.User;
import org.apache.ibatis.annotations.Param;
import java.util.HashMap;
import java.util.List;
public interface UserMapper {
public List<User> findUserByUsername(@Param("username") String username);
public void addUser(User user);
public User findUserById(int id);
public List<User> findUserByPasswordAndSex(@Param("p") String password, @Param("sex") int sex);
public List<User> findUserByHash(HashMap<String,Object> map);
// 实际开发中有分表分库,分表:mysql中一张表存储数据是百万级别性能是最好的。
// 如下1千万信息放一张表性能低,所以分表两张表,根据表名查询用户的信息
public List<User> findUserByTable(@Param("tableName") String tableName);
public List<User> findUserLikeUsername(@Param("username") String username);
// 如下自定义结果集(驼峰映射和起别名不起作用)
public List<User> findUsersBySex(@Param("sex") int sex);
// 如下查询年龄小于某个指定的值的用户信息
public List<User> findUsersByAge(@Param("age") int age);
}
2.3 test
package com.itheima.mapper;
import com.itheima.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import static org.junit.Assert.*;
public class UserMapperTest {
private UserMapper userMapper;
@Before
public void setUp() throws Exception {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void findUserById() {
User user = userMapper.findUserById(1);
System.out.println(user);
}
@Test
public void addUser(){
User user = new User();
user.setUserName("zhangwuji");
user.setPassword("zhaoming");
user.setName("zhouzhiruo");
userMapper.addUser(user); //user没有id信息,但UserMapper.xml中配置了主键id回显
System.out.println(user.getId()); //执行后数据库插入一条id=9,删除id=9后插入一条id=10不是9
}
@Test
public void findUserByPasswordAndSex(){
String password = "123456";
int sex = 1;
List<User> userList = userMapper.findUserByPasswordAndSex(password, sex);
for(User user:userList){
System.out.println(user);
}
}
@Test
public void findUserByUsername(){
List<User> userList = userMapper.findUserByUsername("lisi");
for(User user:userList){
System.out.println(user);
}
}
@Test
public void findUserByHash(){
HashMap<String,Object> map = new HashMap<>();
map.put("pwd","123456");
map.put("sex","1");
List<User> userList = userMapper.findUserByHash(map);
for(User user:userList){
System.out.println(user);
}
}
@Test
public void findUserByTable(){
String tableName = "tb_user_copy";
Listmybatis中的一些标签使用
mybatis源码配置文件解析之五:解析mappers标签(解析class属性)