1、mybatis的进阶
1.1、对于数据库表和实体类不一致处理
这里主要处理XXXMapper.xml中,<select>标签数据库表中字段和实体类中属性不一致情况。对于查询出的结果会自动封装给类中的属性,如果两个名称不一致那么就会封装不了。
举例:数据库表中的字段名称为:
而我们定义类中的属性为:
private Integer id;
private String name;
可以清楚的发现,字段和数据库中两个不一样,所以mybatis不会帮我们自动进行封装,这样怎么处理呢?
- 第一种方式:
我们可以在写sql语句的时候将字段起个别名,这样就会将查询出的结果封装给类中。
select t_id id, t_name name from t_category;
这样处理是将数据库中的字段进行起别名,名称和实体类中的属性一致,这样虽然可以达到效果,但是不推荐,因为我们写的SQL语句会很多,如果每一个都需要这样起别名,那么我们会很麻烦。
- 第二种方式:
还记得<select>标签中resultType属性么?这个是帮助我们自动封装给一个pojo,但是如果要用不一致的情况,那么就要使用<resultMap>
<!-- 查询所有的老师 -->
<select id="selectAll" resultMap="TeacherMap">
select * from t_teacher
</select>
<resultMap type="Teacher" id="TeacherMap">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
</resultMap>
- 我们可以看到有resultMap属性,但是下面也有一个resultMap标签,其中<select>的resultMap值和下面<resultMap>中id一致,这样就可以找到对应的关系。
- 下面内含有两个标签<id>和<result> property是实体类中的属性名,column数据库中的字段名。
- <resultMap>中有一个type属性,这个的值就是写你要查询的那个类型。比如:t_teacher和Teacher要对应,那么这个type就要写Teacher。
1.2、出现一对多关系处理方式
- 对于我们数据库表中,经常出现一类情况就是一对多,那么如何处理呢?
首先分析一下一对多在数据库建表的时候怎么确定,我有两个表t_category和t_product。
t_category,如下:
t_product,如下:
外键在设立的时候是在一对多,多的那一方,种类和商品一对多,一个种类有多个商品,所以我们分析出来多的那一个方面是设立外键的,即在t_product表中设立一个外键,外键要和t_category中的主键有关系,我们升级一下t_product表。
- 表建立完成后要有实体类与之对应,那么外键关系在实体类中怎么体现呢?
答案是,相反的,一对多在java中表示为List<>,那么在实体类中封装就是在Category类中写List<Product>。
import java.util.List;
public class Category {
private Integer id;
private String name;
private List<Product> products;
public Category() {
}
public Category(Integer id, String name, List<Product> products) {
this.id = id;
this.name = name;
this.products = products;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
@Override
public String toString() {
return "Category [id=" + id + ", name=" + name + ", products=" + products + "]";
}
}
- 如果我有一个一对一关系怎么确定呢?
外键在那个表也都可以,但是实体类中也是相反的,和一对多关系一样的。
举例:商品和评价是一对一关系,那么我们可以在t_review添加一个外键,外键是和商品表的主键一致。
t_review表,如下:
2、mybatis升级练习
有三个表,分别是t_review(评价表),t_product(商品表),t_category(种类表),我们要查询所有信息,怎么操作?
- 第一步,导入所需要的jar包。
- 编写与表相对应的实体类。
public class Category {
private Integer id;
private String name;
private List<Product> products;
public Category() {
}
public Category(Integer id, String name, List<Product> products) {
this.id = id;
this.name = name;
this.products = products;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
@Override
public String toString() {
return "Category [id=" + id + ", name=" + name + ", products=" + products + "]";
}
}
public class Product {
private Integer id;
private String name;
private Review review;
public Product() {
}
public Product(Integer id, String name, Review review) {
this.id = id;
this.name = name;
this.review = review;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Review getReview() {
return review;
}
public void setReview(Review review) {
this.review = review;
}
@Override
public String toString() {
return "Product [id=" + id + ", name=" + name + ", review=" + review + "]";
}
}
public class Review {
private Integer id;
private String value;
public Review() {
}
public Review(Integer id, String value) {
this.id = id;
this.value = value;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "Review [id=" + id + ", value=" + value + "]";
}
}
- 写完之后需要写出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>
<typeAliases>
<typeAlias alias="Category" type="com.domain.Category" />
<typeAlias alias="Product" type="com.domain.Product" />
<typeAlias alias="Review" type="com.domain.Review" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/te01" />
<property name="username" value="root" />
<property name="password" value="12345" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="CategoryMapper.xml"/>
</mappers>
</configuration>
- 写对应的接口。
import java.util.List;
import com.domain.Category;
public interface ICategory {
public List<Category> selectAll();
public Category selectOne(Integer categoryId);
}
- 写出CategoryMapper.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.interfaces.ICategory">
<!-- 查询所有的产品信息 -->
<select id="selectAll" resultMap="CategoryMap">
SELECT * FROM t_category c, t_product p, t_review r WHERE c.`c_id` = p.`c_id` AND p.`p_id` = r.`p_id`
</select>
<!-- 依据主键查询所有商品的信息 -->
<select id="selectOne" parameterType="int" resultMap="CategoryMap">
SELECT * FROM t_category c, t_product p, t_review r WHERE c.`c_id` = p.`c_id` AND p.`p_id` = r.`p_id` AND c.c_id=#{id}
</select>
<resultMap type="Category" id="CategoryMap">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<collection property="products" ofType="Product">
<id property="id" column="p_id"/>
<result property="name" column="p_name"/>
<association property="review" javaType="Review">
<id property="id" column="r_id"/>
<result property="value" column="r_value"/>
</association>
</collection>
</resultMap>
</mapper>
- 测试
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import com.interfaces.ICategory;
public class TestToCategory {
// 进行初始化加载配置文件
public static SqlSessionFactory createFac() {
return new SqlSessionFactoryBuilder()
.build(TestToTeacher.class.getClassLoader().getResourceAsStream("mybatis-config.xml"));
}
@Test
public void test1() {
SqlSession session = createFac().openSession();
ICategory category = session.getMapper(ICategory.class);
System.out.println(category.selectAll());
session.close();
}
@Test
public void test2() {
SqlSession session = createFac().openSession();
ICategory category = session.getMapper(ICategory.class);
System.out.println(category.selectOne(1));
session.close();
}
}
3、mybatis实现分页处理
对于分页技术,我们可以有前端分页和后端分页,前端分页我们可以将所有的数据查询出来,利用前端的jquery技术进行分页,当然我们可以用后端分页,这就是我们将要介绍的技术——pagehelper。
1.第一步我们需要导入jar包。
2. 在mybatis-config.xml文件中声明一下pagehelper。
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="offsetAsPageNum" value="true"/>
<property name="helperDialect" value="mysql"/>
<property name="rowBoundsWithCount" value="true"/>
<property name="reasonable" value="true"/>
</plugin>
</plugins>
- 测试
@Test
public void test1() {
SqlSession openSession = createFac().openSession();
TeacherImpl mapper = openSession.getMapper(ITeacher.class);
//分页开始,将设置了一下
PageHelper.startPage(1, 2);
//这一页里面的具体消息,才开始用
PageInfo<Teacher> pageInfo = new PageInfo<>(mapper.selectAll());
System.out.println(pageInfo.getList());
}
startPage()函数,第一个参数是pageNum,第二个参数为pageSize。