文章目录
1 使用MyBatis进行CRUD操作
1.1 根据ID查询user
1.1.1 持久层接口添加findById方法
User findById(Integer userId);
1.1.2 在IUserDao.xml映射配置文件中配置
<select id="findById" resultType="cn.pine.domain.User" parameterType="int">
SELECT * FROM USER WHERE id = #{uid}
</select>
resultType:是指定结果集的类型
parameterType:用于指定传入参数的类型
#{}:代表占位符,作用相当于声明形参
1.1.3 测试
抽取测试类重复代码
public class MybatisTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private IUserDao userDao;
@Before
public void init() throws Exception{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
session = factory.openSession();
userDao = session.getMapper(IUserDao.class);
}
@After
public void destroy() throws Exception{
session.commit();
session.close();
in.close();
}
@Test
public void testFindByID(){
User user = userDao.findById(41);
System.out.println(user);
}
通过Junit 的Before与After注解来抽取重复的测试代码,分别在运行Test开始和结束之后运行,简化代码。
测试结果:
2020-08-24 15:09:50,898 396 [ main] DEBUG cn.pine.dao.IUserDao.findById - ==> Preparing: SELECT * FROM USER WHERE id = ?
2020-08-24 15:09:50,916 414 [ main] DEBUG cn.pine.dao.IUserDao.findById - ==> Parameters: 41(Integer)
2020-08-24 15:09:50,943 441 [ main] DEBUG cn.pine.dao.IUserDao.findById - <== Total: 1
User{id=41, username='甲', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
1.2 保存操作
1.2.1 持久层接口中添加saveUser方法
//返回数据库中影响行数
int saveUser(User user);
1.2.2 映射配置
<insert id="saveUser" parameterType="cn.pine.domain.User">
<selectKey keyColumn="id" keyProperty="id" resultType="int">
SELECT last_insert_id();
</selectKey>
INSERT INTO USER (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})
</insert>
parameterType:传入的参数为对象,填写全限定类名或别名
#{}中填写的是对象的属性,如user.username,但是由于在parameterType已经指定实体类,可以直接填写username。
selectKey标签中获取保存时的id值,并传给参数中的对象。
1.2.3 测试
@Test
public void testSaveUser(){
User user = new User();
user.setUsername("saveUser");
user.setAddress("西安");
user.setSex("男");
user.setBirthday(new Date());
System.out.println("beforeSaving:" + user);
userDao.saveUser(user);
System.out.println("afterSaving:+user);
}
测试结果
beforeSaving:User{id=null, username='saveUser', birthday=Mon Aug 24 15:25:51 CST 2020, sex='男', address='西安'}
afterSavingUser:{id=50, username='saveUser', birthday=Mon Aug 24 15:25:51 CST 2020, sex='男', address='西安'}
1.3 更新操作
1.3.1 持久层接口添加updateUser方法
//返回影响记录行数
int updateUser(User user);
1.3.2 映射配置
<update id="updateUser" parameterType="cn.pine.domain.User">
UPDATE USER SET username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}WHERE id=#{id}
</update>
1.3.3 测试
@Test
public void testUpdateUser() {
User user = userDao.findById(48);
user.setAddress("成都");
int res = userDao.updateUser(user);
System.out.println(res);
}
输出1,表示更新成功。
1.4 删除操作
1.4.1 持久层接口中添加deleteUser方法
//返回影响条数
int deleteUser(Integer userId);
1.4.2 映射配置
<delete id="deleteUser" parameterType="java.lang.Integer">
DELETE FROM USER WHERE id=#{uid}
</delete>
1.4.3 测试
@Test
public void testDeleteUser() {
int res = userDao.deleteUser(50);
System.out.println(res);
}
输出1,执行成功。
1.5 用户模糊查询
1.5.1 持久层接口中添加findByName方法
List<User> findByName(String username);
1.5.2 映射配置
<select id="findByName" resultType="cn.pine.domain.User" parameterType="String">
SELECT * FROM USER WHERE username like #{username}
</select>
1.5.3 测试
@Test
public void testFindByName() {
List<User> users = userDao.findByName("%甲%");
for (User user : users) {
System.out.println(user);
}
}
返回结果
User{id=41, username='甲', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
1.6 查询使用聚合函数
1.6.1 持久层接口添加方法
int findTotal();
1.6.2 映射配置
<select id="findTotal" resultType="int">
SELECT COUNT(*) FROM USER
</select>
1.6.3 测试
@Test
public void testFindTotal() {
int total = userDao.findTotal();
System.out.println(total);
}
返回6,为数据库中总条数。
2 包装对象传递输入参数
2.1 QueryVo包装类
public class QueryVo implements Serializable {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
2.2 持久层接口添加findByVo方法
List<User> findByVo(QueryVo vo);
2.3 映射配置
<select id="findByVo" resultType="cn.pine.domain.User" parameterType="cn.pine.domain.QueryVo">
SELECT * FROM USER WHERE username LIKE #{user.username}
</select>
2.4 测试
包装类作参数
@Test
public void testFindByVo(){
QueryVo queryVo = new QueryVo();
User user = new User();
user.setUsername("%甲%");
queryVo.setUser(user);
List<User> users = userDao.findByVo(queryVo);
for (User u : users) {
System.out.println(u);
}
}
返回结果
User{id=41, username='甲', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
3 输出结果封装
当实体类属性与数据库表中的列名不一致时,对输出结果封装可以有两种方法。
- 修改映射配置中的SQL语句,例如将原来的列明起与实体类属性一致的别名select columnName from tableName 换为 select columnName as propetyName from tableName
- 在接口配置文件映射配置中使用resultMap
<resultMap type="className" id="xxxMap">
<id column="primary_column" property="propertyA"/>
<result column="columnB" property="propertyB"/>
...
<result column="columnG" property="propertyG"/>
</resultMap>
<select id='funcName' resultMap="xxxMap">
select * from tableName
</select>
4 SqlMapConfig.xml配置内容
4.1 配置内容与顺序
-properties(属性)
--property
-settings(全局配置参数)
--setting
-typeAliases(类型别名)
--typeAliase
--package
-typeHandlers(类型处理器)
-objectFactory(对象工厂)
-plugins(插件)
-environments(环境集合属性对象)
--environment(环境子属性对象)
---transactionManager(事务管理)
---dataSource(数据源)
-mappers(映射器)
--mapper
--package
4.2 properties
有两种方式进行配置
-
<properties> <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="jdbc.username" value="root"/> <property name="jdbc.password" value="root"/> </properties>
-
先在类路径下创建jdbcConfig.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
再配置propety标签
<properties url="file:///绝对路径/jdbcConfig.properties">
</properties>
经过以上properties的配置后,dataSource标签就可以引用以上配置
<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>
4.3 typeAliases(类型别名)
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="别名" type="全限定类名"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.pine.domain"/>
<package name="其它包"/>
</typeAliases>
4.4 mappers(映射器)
1.使用相对于类路径的资源
如:<mapper resource="com/pine/dao/IUserDao.xml" />
2.使用 mapper 接口类路径
如:<mapper class="com.pine.dao.UserDao"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
3.注册指定包下的所有 mapper 接口
如:<package name="cn.pine.mybatis.mapper"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。