MyBatist核心配置文件
1.typeHandlers标签
无论是MyBaits在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成Java类型。下表描述了一些默认的类型处理器。
我们可以重写类型处理器或者创建自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现org.apache.ibatis.TypeHandler接口,或继承一个很便利的类org.apache.ibatis.BaseTypeHandler,然后可以选择性地将它映射到一个JDBC类型。例如需求:一个Java中的Date数据类型,我想将它中存到数据库的时候存成一个1970至今的毫秒数,取出来的时候转换成java的Date,即java的Date与数据库的varchar毫秒值之间转换。
开发步骤:
①定义转换类继承类BaseTypeHandler
②覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时mysql的字符串类型转换成java的Type类型的方法
③在MyBaits核心配置文件中进行注册
④测试转换是否正确
代码示例:
//UserMapper.xml
<insert id="save" parameterType="com.xc.domain.User">
insert into user value(#{id},#{username},#{password},#{birthday})
</insert>
代码示例:
定义转换类继承类BaseTypeHandler;覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时mysql的字符串类型转换成java的Type类型的方法
//DateTypeHandler.java
public class DateTypeHandler extends BaseTypeHandler<Date> {
//将java类型转换成数据库需要的类型
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
long time = date.getTime();
preparedStatement.setLong(i,time);
}
//将数据库中的某些类型转换成java类型
//String参数是要转换的数据库中表的字段的名称,ResultSet是查询出的结果集
@Override
public Date getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
//获取结果集中我们需要的数据(long)转换成Date类型并返回
long aLong = resultSet.getLong(columnName);
Date date = new Date(aLong);
return date;
}
//将数据库中的某些类型转换成java类型
@Override
public Date getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
//获取结果集中我们需要的数据(long)转换成Date类型并返回
long aLong = resultSet.getLong(columnIndex);
Date date = new Date(aLong);
return date;
}
//将数据库中的某些类型转换成java类型
@Override
public Date getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
//获取结果集中我们需要的数据(long)转换成Date类型并返回
long aLong = callableStatement.getLong(columnIndex);
Date date = new Date(aLong);
return date;
}
}
代码示例:
//MapperTest.java
@Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//创建user
User user = new User();
user.setUsername("小L");
user.setPassword("789");
user.setBirthday(new Date());
//执行保存操作
mapper.save(user);
sqlSession.commit();
sqlSession.close();
}
测试截图:
上述是存入数据库时转换成varchar类型,以下是读取时转换成Date类型:
代码示例:
//UserMapper.xml
<select id="findById" parameterType="int" resultType="com.xc.domain.User">
select * from user where id=#{id}
</select>
代码示例:
//MapperTest.java
@Test
public void test2() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findById(7);
System.out.println("user中的birthday:" + user.getBirthday());
sqlSession.commit();
sqlSession.close();
}
//DateTypeHandler.java同上未改变
测试截图:
2.plugins标签
MyBaits可以使用第三方的插件来对功能进行扩展,分页助手PageHandler是将分页的复杂操作进行拼接,使用简单的方式即可获得分页的相关数据。
开发步骤:
①导入通用PageHelper的坐标
②在mybaits核心配置文件中配置PageHandler插件
③测试分页数据获取
代码示例:
//在pom.xml导入通用PageHelper的坐标
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
代码示例:
//在mybaits核心配置文件sqlMapperConfig.xml中配置PageHandler插件
<!--配置分页助手插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
代码示例:
//在MapperTest.java测试分页数据获取
@Test
public void test3() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//设置分页的相关参数:当前页+每页显示的条数
PageHelper.startPage(1,3);//表示查询第一页,每页显示三条数据
List<User> userList = mapper.findAll();
for (User user : userList) {
System.out.println(user);
}
//获得与分页相关的数据
PageInfo<User> pageInfo = new PageInfo<User>(userList);
System.out.println("当前页:" + pageInfo.getPageNum());
System.out.println("每页显示条数:" + pageInfo.getPageSize());
System.out.println("总条数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
System.out.println("上一页:" + pageInfo.getPrePage());
System.out.println("下一页:" + pageInfo.getNextPage());
System.out.println("是否是第一页:" + pageInfo.isIsFirstPage());
System.out.println("是否是最后一页:" + pageInfo.isIsLastPage());
sqlSession.commit();
sqlSession.close();
}
测试截图:
MyBaits的多表操作
1.一对一查询
一对一查询的模型
用户和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户一对一的查询需求:查询一个订单与此同时查询出该订单所属的用户。
代码示例:
//OrderMapper.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.xc.mapper.OrderMapper">
<resultMap id="orderMap" type="com.xc.domain.Order">
<!--手动指定字段与实体属性的映射关系
column:数据表的字段名称
property:实体的属性名称-->
<id column="oid" property="id"/>
<id column="ordertime" property="ordertime"/>
<id column="total" property="total"/>
<!--第一种写法-->
<id column="uid" property="user.id"/>
<id column="username" property="user.username"/>
<id column="password" property="user.password"/>
<id column="birthday" property="user.birthday"/>
<!--第二种写法
property:当前实体(order)中的属性名称(private User user)
javaType:代表当前实体中的属性的类型(User)
-->
<association property="user" javaType="com.xc.domain.User">
<id column="uid" property="id"/>
<id column="username" property="username"/>
<id column="password" property="password"/>
<id column="birthday" property="birthday"/>
</association>
</resultMap>
<select id="findAll" resultMap="orderMap">
select * ,o.id oid from orders o,user u where o.uid=u.id
</select>
</mapper>
代码示例:
//OrderMapper.java
public interface OrderMapper {
public List<Order> findAll();
}
代码示例:
//MapperTest.java
@Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
List<Order> orderList = mapper.findAll();
for (Order order : orderList) {
System.out.println(order);
}
sqlSession.close();
}
测试截图:
2.一对多查询
一对多查询的模型
用户和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户,一对多的查询需求:查询一个订单与此同时查询出该用户所具有的订单。
代码示例:
//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.xc.mapper.UserMapper">
<resultMap id="userMap" type="com.xc.domain.User">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!--配置集合
collection:集合
property:集合名称
ofType:集合当中的数据类型
-->
<collection property="orderList" ofType="com.xc.domain.Order">
<!--封装Order的数据-->
<id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="userMap">
select * from user u,orders o where u.id=o.uid
</select>
</mapper>
测试截图:
3.多对多查询
一多对多查询的模型
用户和订单表的关系为,一个用户有多个订单,一个角色被多个用户使用,多对多的查询需求:查询出用户同时查询出该用户的所有角色。
代码示例:
//UserMapper.xml
<resultMap id="userRoleMap" type="com.xc.domain.User">
<!--user的信息-->
<id column="userid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!--user内部的roleList信息-->
<collection property="roleList" ofType="com.xc.domain.Role">
<id column="roleId" property="id"></id>
<result column="roleName" property="roleName"></result>
<result column="roleDesc" property="roleDesc"></result>
</collection>
</resultMap>
<select id="findUserAndRoleAll" resultMap="userRoleMap">
select * from user u,user_role ur,role r where u.id=ur.userId and ur.roleId=r.id
</select>
代码示例:
//Role.java
package com.xc.domain;
public class Role {
private int id;
private String roleName;
private String roleDesc;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
代码示例:
//UserMapper.java
public interface UserMapper {
public List<User> findAll();
public List<User> findUserAndRoleAll();
}
代码示例:
//MapperTest.java
@Test
public void test3() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userAndRoleAll = mapper.findUserAndRoleAll();
for (User user : userAndRoleAll) {
System.out.println(user);
}
sqlSession.close();
}
测试截图:
MyBaits的注解开发
1.MyBaits的常用注解
- @Insert:实现新增
- @Update:实现更新
- @Delete:实现删除
- @Select:实现查询
- @Result:实现结果集封装
- @Results:可以与@Result一起使用,封装多个结果集
- @One:实现一对一结果集封装
- @Many:实现一对多结果集封装
2.MyBaits的增删改查(使用注解开发)
代码示例:
//UserMapper.java
public interface UserMapper {
@Insert("insert into user values(#{id},#{username},#{password},#{birthday})")
public void save(User user);
@Update("update user set username=#{username},password=#{password},birthday=#{birthday} where id=#{id}")
public void update(User user);
@Delete("delete from user where id=#{id}")
public void delete(int id);
@Select("select * from user where id=#{id}")
public User findById(int id);
@Select("select * from user")
public List<User> findAll();
}
代码示例:
//sqlMapperConfig.xml
<!--加载映射关系-->
<mappers>
<!--指定接口所在的包-->
<package name="com.xc.mapper"/>
</mappers>
代码示例:
//MyBatisTest.java
public class MyBatisTest {
private UserMapper mapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void testSave() throws IOException {
User user = new User();
user.setUsername("小H");
user.setPassword("hij");
mapper.save(user);
}
@Test
public void testUpdate() throws IOException {
User user = new User();
user.setId(5);
user.setUsername("小E");
user.setPassword("789");
mapper.update(user);
}
@Test
public void testDelete() throws IOException {
User user = new User();
mapper.delete(8);
}
@Test
public void testFindById() throws IOException {
User user = mapper.findById(1);
System.out.println(user);
}
@Test
public void testFindAll() throws IOException {
List<User> all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
}
}
测试截图:
3.MyBaits的注解实现复杂映射开发
实现复杂关系之前我们可以在映射文件中通过配置< resultMap >来实现,使用注解开发后,我们可以使用@Results注解,@Result,@One注解,@Many注解组合完成复杂关系的配置
(1)一对一查询的注解开发
代码示例:
//OrderMapper.java
public interface OrderMapper {
方法一:
@Select("select *, o.id oid from orders o, user u where o.uid=u.id")
@Results({
@Result(column = "oid",property = "id"),
@Result(column = "ordertime",property = "ordertime"),
@Result(column = "total",property = "total"),
@Result(column = "uid",property = "user.id"),
@Result(column = "password",property = "user.password"),
@Result(column = "password",property = "user.password"),
@Result(column = "birthday",property = "user.birthday")
})
方法二(用的较多):
@Select("select * from orders")
@Results({
@Result(column = "id",property = "id"),
@Result(column = "ordertime",property = "ordertime"),
@Result(
property = "user", //要封装的属性名称
column = "id", //根据该字段去查询user表的数据
javaType = User.class, //要封装的实体类型
//select属性代表查询哪个接口的方法获得数据
one = @One(select = "com.xc.mapper.UserMapper.findById")
)
})
public List<Order> findAll();
}
代码示例:
//MyBatisTest2.java
public class MyBatisTest2 {
private OrderMapper mapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(OrderMapper.class);
}
@Test
public void testfindAll() throws IOException {
List<Order> all = mapper.findAll();
for (Order order : all) {
System.out.println(order);
}
}
}
测试截图:
(2)一对多查询的注解开发
代码示例:
//OrderMapper.java
@Select("select * from orders where uid=#{uid}")
public List<Order> findBuUid(int uid);
代码示例:
//UserMapper.java
@Select("select * from user")
@Results({
@Result(id = true, column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(
property = "orderList",
column = "id",
javaType = List.class,
many = @Many(select = "com.xc.mapper.OrderMapper.findByUid")
)
})
public List<User> findUserAndOrderAll();
代码示例:
//MyBatisTest3.java
public class MyBatisTest3 {
private UserMapper mapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void test1() throws IOException {
List<User> all = mapper.findUserAndOrderAll();
for (User user : all) {
System.out.println(user);
}
}
}
测试截图:
(3)多对多查询的注解开发
代码示例:
//UserMapper.java
@Select("select * from user")
@Results({
@Result(id = true,column = "id",property = "id"),
@Result(id = true,column = "username",property = "username"),
@Result(id = true,column = "password",property = "password"),
@Result(
property = "roleList",
column = "id",
javaType = List.class,
many = @Many(select = "com.xc.mapper.RoleMapper.findByUid")
)
})
public List<User> findUserAndRoleAll();
代码示例:
//RoleMapper.java
public interface RoleMapper {
@Select("select * from user_role ur,role r where ur.roleId=r.id and ur.userId=#{uid}")
public List<Role> findByUid(int uid);
}
代码示例:
//MyBatisTest4.java
public class MyBatisTest4 {
private UserMapper mapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapperConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void test1() throws IOException {
List<User> all = mapper.findUserAndRoleAll();
for (User user : all) {
System.out.println(user);
}
}
}
测试截图: