【精选】框架初探篇之——MyBatis的CRUD及配置文件
MyBatis增删改查
MyBatis新增
新增用户
-
持久层接口添加方法
void add(User user);
-
映射文件添加标签
<insert id="add" parameterType="com.mybatis.pojo.User"> insert into user(username,sex,address) values(# {username},# {sex},# {address}) </insert>
-
编写测试方法
@Test public void testAdd() throws Exception { InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); SqlSession session = factory.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); User user = new User("程序员", "男", "上海"); userMapper.add(user); // 提交事务 session.commit(); session.close(); is.close(); }
注意:
- 当接口方法的参数类型为POJO类型时,SQL语句中绑定参数时使用
# {POJO的属性名}
即可。- MyBatis事务默认手动提交,所以在执行完增删改方法后,需要手动调用SqlSession对象的事务提交方法,否则数据库将不发生改变。
MyBatis修改
优化测试类
我们发现MyBatis的测试方法在操作数据库前都需要获取代理对象,操作数据库后都需要释放资源,可以利用Junit的前置后置方法,优化测试类代码。
InputStream is = null;
SqlSession session = null;
UserMapper userMapper = null;
@Before
public void before() throws IOException {
// (1)读取核心配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
// (2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// (3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
// (4)SqlSessionFactory对象获取SqlSession对象
session = factory.openSession();
// (5)获取代理对象
userMapper = session.getMapper(UserMapper.class);
}
@After
public void after() throws IOException {
// 释放资源
session.close();
is.close();
}
这样Junit就会自动执行获取代理对象和释放资源的方法。
修改用户
-
持久层接口添加方法
void update(User user);
-
映射文件添加标签
<update id="update" parameterType="com.mybatis.pojo.User"> update user set username = #{username}, sex = #{sex}, address=#{address} where id = #{id} </update>
-
编写测试方法
@Test public void testUpdate(){ User user = new User(8,"程序员1","女","深圳"); userMapper.update(user); session.commit(); }
MyBatis删除、根据Id查询
删除用户
-
持久层接口添加方法
void delete(int userId);
-
映射文件添加标签
<delete id="delete" parameterType="int"> delete from user where id = #{id} </delete>
注:当方法的参数类型是简单数据类型时,#{}中可以写任意名称
- 简单数据类型:基本数据类型、字符串等
-
编写测试方法
@Test public void testDelete(){ userMapper.delete(8); session.commit(); }
根据ID查询用户
-
持久层接口添加方法
User findById(int userId);
-
映射文件添加标签
<select id="findById" parameterType="int" resultType="com.mybatis.pojo.User"> select * from user where id = #{userId} </select>
-
编写测试方法
@Test public void testFindById(){ User user = userMapper.findById(1); System.out.println(user); }
MyBatis模糊查询
使用#定义参数
-
持久层接口添加方法
List<User> findByNameLike(String username);
-
映射文件添加标签
<select id="findByNameLike" parameterType="string" resultType="com.mybatis.user.User"> select * from user where username like #{name} </select>
-
编写测试方法
@Test public void testFindByNameLike(){ List<User> users = userMapper.findByNameLike("%王%"); for (User user:users){ System.out.println(user); } }
我们看到在映射文件中,parameterType的值为
string
而没有写java.lang.String
,这是为什么呢?
- 参数/返回值类型为基本数据类型/包装类/String等类型时,我们可以写全类名,也可以写别名。
数据类型 | 别名 |
---|---|
byte | _byte |
long | _long |
short | _short |
int | _int |
int | _integer |
double | _double |
float | _float |
boolean | _boolean |
String | string |
Byte | byte |
Long | long |
Short | short |
Integer | int/integer |
Double | double |
Float | float |
Boolean | boolean |
Date | date |
BigDecimal | decimal/bigdecimal |
Object | object |
Map | map |
HashMap | hashmap |
List | list |
ArrayList | arraylist |
Collection | collection |
Iterator | iterator |
使用$定义参数
模糊查询如果不想在调用方法时参数加%,可以使用拼接参数的方式设置Sql:
<select id="findByUsernameLike" parameterType="string" resultType="com.mybatis.pojo.User">
select * from user where username like '%${value}%'
</select>
测试方法写法如下:
@Test
public void testFindByNameLike(){
List<User> users = userMapper.findByUsernameLike("张三");
users.forEach(System.out::println);
}
#和$的区别:
- #表示sql模板的占位符,$表示将字符串拼接到sql模板中。
- #可以防止sql注入,一般能用#就不用$。
- ${}内部的参数名必须写value。
使用< bind>定义参数
如果使用#
还不想在调用方法的参数中添加%
,可以使用<bind>
标签,<bind>
标签允许我们在 Sql语句以外创建一个变量,并可以将其绑定到当前的Sql语句中。用法如下:
<select id="findByUsernameLike" parameterType="string" resultType="com.mybatis.pojo.User">
<bind name="likeName" value="'%'+username+'%'"/>
select * from user where username like #{likeName}
</select>
测试方法写法如下:
@Test
public void testFindByNameLike(){
List<User> users = userMapper.findByUsernameLike("张三");
users.forEach(System.out::println);
}
MyBatis分页查询
分页查询时,Sql语句使用limit关键字,需要传入开始索引和每页条数两个参数。MyBatis的多参数处理有以下方式:
顺序传参
Sql中的参数使用arg0,arg1…或param1,param2…表示参数的顺序。此方法可读性较低,在开发中不建议使用。
-
持久层接口方法
/** * 分页查询 * @param startIndex 开始索引 * @param pageSize 每页条数 * @return */ List<User> findPage(int startIndex,int pageSize);
-
映射文件
<select id="findPage" resultType="com.mybatis.mapper.User"> select * from user limit #{arg0},#{arg1} </select> <select id="findPage" resultType="com.mybatis.mapper.User"> select * from user limit #{param1},#{param2} </select>
-
测试类
@Test public void testFindPage(){ List<User> users = userMapper.findPage(0,3); users.forEach(System.out::println); }
@Param传参
在接口方法的参数列表中通过@Param定义参数名称,在Sql语句中通过注解中所定义的参数名称指定参数位置。此方式参数比较直观的,推荐使用。
-
持久层接口方法
List<User> findPage1(@Param("startIndex") int startIndex, @Param("pageSize")int pageSize);
-
映射文件
<select id="findPage1" resultType="com.mybatis.mapper.User"> select * from user limit #{startIndex},#{pageSize} </select>
-
测试类
@Test public void testFindPage1(){ List<User> users = userMapper.findPage1(3,3); users.forEach(System.out::println); }
POJO传参
自定义POJO类,该类的属性就是要传递的参数,在SQL语句中绑定参数时使用POJO的属性名作为参数名即可。此方式推荐使用。
-
自定义POJO
public class PageQuery { private int startIndex; private int pageSize; // 省略getter/setter/构造方法 }
-
持久层接口方法
List<User> findPage2(PageQuery pageQuery);
-
映射文件
<select id="findPage2" resultType="com.mybatis.pojo.User" parameterType="com.mybatis.pojo.PageQuery"> select * from user limit #{startIndex},#{pageSize} </select>
-
测试类
@Test public void testFindPage2(){ PageQuery pageQuery = new PageQuery(3, 3); List<User> users = userMapper.findPage2(pageQuery); users.forEach(System.out::println); }
Map传参
如果不想自定义POJO,可以使用Map作为传递参数的载体,在SQL语句中绑定参数时使用Map的Key作为参数名即可。此方法推荐使用。
-
持久层接口方法
List<User> findPage3(Map<String,Object> params);
-
映射文件
<select id="findPage3" resultType="com.mybatis.pojo.User" parameterType="map"> select * from user limit #{startIndex},#{pageSize} </select>
-
测试类
@Test public void testFindPage3(){ Map<String,Object> params = new HashMap(); params.put("startIndex",0); params.put("pageSize",4); List<User> users = userMapper.findPage3(params); users.forEach(System.out::println); }
MyBatis聚合查询、主键回填
查询用户总数
-
持久层接口方法
int findCount();
-
映射文件
<select id="findCount" resultType="int"> select count(id) from user </select>
-
测试类
@Test public void testFindCount(){ System.out.println(userMapper.findCount()); }
主键回填
有时我们需要获取新插入数据的主键值。如果数据库中主键是自增的,这时我们就需要使用MyBatis的主键回填功能。
-
持久层接口方法
void add(User user);
-
映射文件
<insert id="add" parameterType="com.mybatis.user.User"> <!-- keyProperty:主键属性名,keyColumn:主键列名,resultType:主键类型,order:执行时机 --> <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER"> SELECT LAST_INSERT_ID(); </selectKey> insert into user(username,sex,address) values(#{username},#{sex},#{address}) </insert>
SELECT LAST_INSERT_ID():查询刚刚插入的记录的主键值,只适用于自增主键,且必须和insert语句一起执行。
-
测试类
@Test public void testAdd(){ User user = new User("×××", "男", "北京"); userMapper.add(user); session.commit(); System.out.println(user.getId()); }
MyBatis配置文件
< properties>标签
MyBatis配置文件结构:
-configuration
-properties(属性)
-property
-settings(全局配置参数)
-setting
-plugins(插件)
-plugin
-typeAliases(别名)
-typeAliase
-package
-environments(环境)
-environment
-transactionManager(事务管理)
-dataSource(数据源)
-mappers(映射器)
-mapper
-package
properties
属性值定义。properties标签中可以定义属性值,也可以引入外部配置文件。无论是内部定义还是外部引入,都可以使用 ${name}
获取值。
例如:我们可以将数据源配置写到外部的db.properties中,再使用properties标签引入外部配置文件,这样可以做到动态配置数据源。
-
编写db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password=root
-
在配置文件中引入db.properties
<properties resource="db.properties"></properties> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <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>
当然我们也可以将数据源数据通过<properties>
配置到MyBatis配置文件内,但这样做没什么意义。
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"></property>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis"></property>
<property name="jdbc.username" value="root"></property>
<property name="jdbc.password" value="root"></property>
</properties>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<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>
< settings>标签
<settings>
是配置MyBatis运行时的一些行为的,例如缓存、延迟加载、命名规则等一系列控制性参数。后期我们会使用该标签配置缓存和延迟加载等。
< plugins>标签
<plugins>
是配置MyBatis插件的。插件可以增强MyBatis功能,比如进行sql增强,打印日志,异常处理等。后期我们会使用该标签配置分页插件。
< typeAliases>标签
MyBatis对常用类有默认别名支持,比如java.lang.Stirng的别名为string。除此之外,我们也可以使用<typeAliases>
设置自定义别名。
为一个类配置别名
<typeAliases>
<typeAlias type="全类名" alias="别名"></typeAlias>
</typeAliases>
此时我们即可在映射文件中使用自定义别名,如:
-
配置文件:
<typeAliases> <typeAlias type="com.mybatis.pojo.User" alias="User"> </typeAlias> </typeAliases>
-
映射文件:
<select id="findAll" resultType="User"> select * from user </select>
为一个所有包下的所有类配置别名
<typeAliases>
<package name="包名"></package>
</typeAliases>
此时该包下的所有类都有了别名,别名省略包名,和类名相同。如:
-
配置文件:
<typeAliases> <package name="com.mybatis.pojo"></package> </typeAliases>
-
映射文件:
<select id="findPage2" resultType="User" parameterType="PageQuery"> select * from user limit #{startIndex},#{pageSize} </select>
< environments>标签
<environments>
可以为MyBatis配置数据环境。
事务管理
<environments default="mysql">
<environment id="mysql">
<!-- JDBC:使用JDBC的提交和回滚 MANAGED:不做事务处理-->
<transactionManager type="JDBC"></transactionManager>
</environment>
</environments>
连接池
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<!-- 连接池设置 -->
<dataSource type="POOLED">
<!-- 数据源设置... -->
</dataSource>
</environment>
</environments>
dataSource的type属性:
- POOLED:使用连接池管理连接,使用MyBatis自带的连接池。
- UNPOOLED:不使用连接池,直接由JDBC连接。
- JNDI:由JAVAEE服务器管理连接,如果使用Tomcat作为服务器则使用Tomcat自带的连接池管理。
< mappers>标签
<mappers>
用于注册映射文件或持久层接口,只有注册的映射文件才能使用,共有四种方式都可以完成注册:
-
使用相对路径注册映射文件
<mappers> <mapper resource="com/mybatis/mapper/UserMapper.xml"/> </mappers>
-
使用绝对路径注册映射文件
<mappers> <mapper url="file:///C:\Users\a\IdeaProjects\mybatiscase\mybatisDemo1\src\main\resources\com\mybatis\mapper\UserMapper.xml"/> </mappers>
-
注册持久层接口
<mappers> <mapper class="com.mybatis.mapper.UserMapper"/> </mappers>
-
注册一个包下的所有持久层接口
<mappers> <package name="com.mybatis.mapper"/> </mappers>