九、持久层框架(MyBatis)

时间:2023-03-08 21:34:11

一、基于MyBatis的对象关系配置(基于XML方式的配置)

注:  MyBatis不能像Hibernate那样,在实体类上配置上注解或者配置xml映射文件,系统启动后就可以自动创建表。因为MyBatis是基于SQL语句的方式来完成ORM映射的,不是像Hibernate那样将字段与属性完全映射出来,所以不能实现自动建表。

1、一对多的关系

Category分类和Product产品是一对多的关系。一个分类对应多个产品

  1.1、修改Category的pojo实体类,给分类提*品Product的集合

package com.demo.pojo;

import java.util.List;

public class Category{
private int id;
private String name;
List<Product> products;//产品集合属性 //属性的getter/setter方法
public int getId(){
return id;
}
public void setId(int 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;
}
}

  1.2、修改Category的xml映射文件(Category.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DID Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.pojo">
<!--resultType和resultMap的区别:1、resultType是直接返回类型的,也就是pojo对象的实体
2、resultMap是对外部resultMap的引用,是key-value关系的映射
3、resultType和resultMap是不能同时存在的-->
<resultMap type="Category" id="categoryBean">
<id column="cat_id" property="id"/><!--由于Category和Product都有id和name属性,mybatis不知道谁是谁的,所以要别名加以区分-->
<result column="cat_name" property="name"/> <!--一对多,property:集合属性值,ofType:集合元素类型-->
<collection property="products" ofType="Product">
<id column="pro_id" property="id"/>
<result column="pro_name" property="name"/>
<result column="price" property="price">
</collection>
</resutlMap> <!--关联Category和Product的表的查询语句-->
<select id="listCategory" resultMap="categoryBean">
select A.*,B.* from category_table A left join product_table B on A.id=B.id
</select>
</mapper>

  1.3、修改mybatis-config.xml

在mybatis-config.xml中增加对Category.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>
<package name="com.demo.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/demo/pojo/Category.xml"/>
<mapper resource="com/demo/pojo/Product.xml"/>
</mappers>
</configuration>

  1.4、测试一对多TestMyBatis

package com.demo.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List; 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 com.demo.pojo.Category;
import com.demo.pojo.Product; public class TestMyBatis{
public static void main(String[] args){
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session=sqlSessionFactory.openSession(); List<Category> list=session.selectList("listCategory"); for(Category category:list){
System.out.println(category);
List<Product> pro_list=category.getProducts();
for(Product product:pro_list){
System.out.println(product);
}
} session.commit();
session.close();
}
}

2、多对一的关系

也就是一对多的反过来吧,Product产品和Category分类是多对一,多个产品对应一个分类。

  2.1修改Product的pojo实体类,提供Category属性

package com.demo.pojo;

public class Product{
private int id;
private String name;
private float price;
private Category category;//分类属性 //属性的getter/setter方法
public int getId(){
return id;
}
public void setId(int id){
this.id=id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public float getPrice(){
return price;
}
public void setPrice(float price){
this.price=price;
}
public Category getCategory(){
return category;
}
public void setCategory(Category category){
this.category=category;
}
}

  2.2、修改Prodcut.xml映射文件

使用assocation标签进行多对一的关系关联,配置。同样还是老问题,因为Category和Product实体类的属性都有id,name所有要进行别名来区分。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DID Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.pojo">
<!--resultType和resultMap的区别:1、resultType是直接返回类型的,也就是pojo对象的实体
2、resultMap是对外部resultMap的引用,是key-value关系的映射
3、resultType和resultMap是不能同时存在的-->
<resultMap type="Product" id="productgoryBean">
<id column="pro_id" property="id"/><!--由于Category和Product都有id和name属性,mybatis不知道谁是谁的,所以要别名加以区分-->
<result column="pro_name" property="name"/> <!--多对一的关系,property:属性名称,javaType属性的类型-->
<association property="category javaType="Category">
<id column="cat_id" property="id"/>
<result column="cat_name" property="name"/>
</association>
</resutlMap> <!--关联Category和Product的表的查询语句-->
<select id="listproduct" resultMap="productBean">
select A.*,B.* from product_table A left join category_table B on A.id=B.id
</select>
</mapper>

  2.3、测试TestMyBatis,代码同上,不在写。

3、多对多的关系

在多对一的基础上,延伸为多对多,User和Product的关系,用户可以购买多个产品,多个也可以购买同一个产品,但是多对多关系比较复杂,为了维护多对多的关系,必须建立一个中间表。可以建立一个Menu表来作为维护表。

  3.1、建立User表

--创建user表
create user_table(
id int(10) not null auto_increment,
name varchar(50) default null,
primary key(id)
)engine=myisam auto_increment=1 default charset=utf-8;

  3.2、建立Menu表

--建立Menu表
create menu_table(
id int(10) not null auto_increment,
pro_id int(10),--产品的id
usr_id int(10),--用户的id
number int,
primary key(id)
)auto_increment=1 default charset=utf-8;

  3.3、建立User的实体类

给user的pojo加入Menu菜单的属性

package com.demo.pojo;

import java.util.List;

public class User {
private int id;
private String name; List<Menu> menu;//中间表的属性 //属性的getter/setter方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Menu> getMenu() {
return menu;
}
public void setMenu(List<Menu> menu) {
this.menu = menu;
} }

  3.4、建立Menu的实体类

用来维护User和Product的关系

package com.demo.pojo;

public class Menu {
private int id;
private int number;//数量
private User user;//用户
private Product product;//产品 //属性的getter/setter方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public User getUsers() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
} }

  3.5、配置User.xml的映射文件

加入对Product属性的配置,以及Menu自己属性的配置

<?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.demo.pojo">
<resultMap type="User" id="userBean"> <!--配置User属性-->
<id column="usr_id" property="id" />
<result column="usr_name" property="name" /> <!--配置Menu自己特有的属性-->
<collection property="menu" ofType="Menu">
<id column="menu_id" property="id" />
<result column="number" property="number" />
<!--配置User与Product的关系-->
<association property="product" javaType="Product">
<id column="pro_id" property="id"/>
<result column="pro_name" property="name"/>
<result column="price" property="price"/>
</association>
</collection> </resultMap> <select id="listUser" resultMap="userBean">
select A.*,B.*,C.* from user_table A
left join menu_table B on A.id =B.id
left join product_ table C on A.id = C.id
</select> <select id="getUser" resultMap="userBean">
select A.*,B.*,C.* from user_table A
left join menu_table B on A.id =B.id
left join product_ table C on A.id = C.id
where A.id = #{id}
</select>
</mapper>

  3.6、配置Product.xml的映射文件

加入对Category的属性配置,实现Prodcut与Category的多对一关系

<?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.demo.pojo">
<resultMap type="Product" id="productBean">
<id column="pro_id" property="id" />
<result column="pro_name" property="name" />
<result column="price" property="price" /> <!-- 配置Product与Category的多对一的关系 -->
<!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
<association property="category" javaType="Category">
<id column="cat_id" property="id"/>
<result column="cat_name" property="name"/>
</association>
</resultMap> <select id="listProduct" resultMap="productBean">
select A.*,B.* from category_ table A
left join product_ table B on A.id = B.id
</select>
<select id="getProduct" resultMap="productBean">
select A.*,B.* from category_ table A
left join product_ table B on A.id = B.id
where A.id = #{id}
</select>
</mapper>

  3.7、配置Menu.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.demo.pojo"> <insert id="addMenu" parameterType="Menu">
insert into menu_table
values(null,#{user.id},#{product.id},#{number})
</insert>
<insert id="deleteMenu" parameterType="Menu">
delete from menu_table
where usr_id = #{user.id} and pro_id = #{product.id}
</insert> </mapper>

  3.8、在mybatis-config.xml配置文件中加入上面的映射文件就行。

二、基于MyBatis的对象关系配置(基于注解方式的配置)

1、一对多的关系

实现注解方式配置,肯定要增加Mapper接口,还是举例Category分类和Product产品的一对多关系

  1.1、增加CategoryMapper接口

注解:@Select注解:获取Category类,也就是用来给select语句起作用的

   @Results注解:有两个注解,@Result获取结果,@Many中调用ProductMapper的listProduct()方法实现一对多关系

import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.demo.pojo.Category; public interface CategoryMapper{ @Select(" select * from category_table ")
@Results({
@Result(property="id",column="id"),
@Result(property="products",javaType=List.class,column="id",many=@Many(select="com.demo.mapper.ProductMapper.listProduct"))
})//@Many中调用ProductMapper的listProduct()方法实现一对多关系
public List<Category> list();
}

  1.2、增加ProductMapper接口

package com.demo.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Select;

import com.demo.pojo.Product;

public interface ProductMapper {

    @Select(" select * from product_table where id = #{id}")
public List<Product> listProduct(int id); }

  1.3、将CategoryMapper和ProductMapper配置到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>
<package name="com.demo.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--将基于注解配置的实体类映射文件Mapper添加进来-->
<mapper class="com.demo.mapper.CategoryMapper"/>
<mapper class="com.demo.mapper.ProductMapper"/>
</mappers>
</configuration>

  1.4、测试注解方式TestMyBatis

package com.demo;

import java.io.IOException;
import java.io.InputStream;
import java.util.List; 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 com.demo.mapper.ProductMapper;
import com.demo.pojo.Product; public class TestMybatis { public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
//加载基于注解方式的映射文件
ProductMapper mapper = session.getMapper(ProductMapper.class); List<Category> list= mapper.list();
for (Category category: list) {
System.out.println(category.getName());
List<Product> pro_list=category.getProducts();
for(Product product:pro_list){
System.out.println(product.getName());
}
} session.commit();
session.close(); }
}

2、多对一关系

同样是反过来,都是增加Mapper接口,Product和Category是多对一关系

  2.1、修改CategoryMapper接口

package com.demo.mapper;

import org.apache.ibatis.annotations.Select;

import com.demo.pojo.Category;

public interface CategoryMapper {
@Select(" select * from category_table where id = #{id}")
public Category get(int id); }

  2.2、修改ProductMapper接口

package com.demp.mapper;

import java.util.List;

import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.demo.pojo.Product; public interface ProductMapper {
@Select(" select * from product_table ")
@Results({
@Result(property="category",column="cid",one=@One(select="com.demo.mapper.CategoryMapper.get"))
}) //@One表示多对一关系
public List<Product> list();
}

  2.3、测试注解方式TestMyBatis

package com.demo;

import java.io.IOException;
import java.io.InputStream;
import java.util.List; 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 com.demo.mapper.ProductMapper;
import com.demo.pojo.Product; public class TestMybatis { public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
//加载基于注解方式的映射文件
ProductMapper mapper = session.getMapper(ProductMapper.class); List<Product> list= mapper.list();
for (Product product : list) {
System.out.println(product + "\t对应的分类是:\t" + product.getCategory().getName());
} session.commit();
session.close(); }
}

3、多对多的关系

还是一样,User和Product的多对多关系

  3.1、修改ProductMapper接口

提供一个根据id获取product_table数据的get方法

package com.demo.mapper;

import org.apache.ibatis.annotations.Select;

import com.demo.pojo.Product;

public interface ProductMapper{
@Select(" select * from product_table where id=#{id}")
public Product get(int id);
}

  3.2、建立UserMapper接口

提供一个list方法,用来建立一对多关系

package com.demo.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.demo.pojo.User; public interface UserMapper { @Select(" select * from user_table where id = #{id}")
@Results({
@Result(property="id",column="id"),
@Result(property="menu",column="id",javaType=List.class,many=@Many(select="com.demo.mapper.MenuMapper.listMenu"))
})
public List<User> list();
}

  3.3、建立MenuMapper接口

提供listMenu方法,建立Product的多对一关系。

package com.demo.mapper;

import java.util.List;

import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.demo.pojo.Menu; public interface MenuMapper { @Select(" select * from menu_table where id = #{id}")
@Results({
@Result(property="product",column="id",one=@One(select="com.demo.mapper.ProductMapper.get"))
})
public List<Menu> listMenu(int id);
}

  3.4、把注解的映射文件加入到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>
<package name="com.demo.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--注释掉原来基于xml配置方式的映射文件-->
<!--
<mapper resource="com/demo/pojo/Category.xml"/>
<mapper resource="com/demo/pojo/Product.xml"/>
<mapper resource="com/demo/pojo/User.xml"/>
<mapper resource="com/demo/pojo/Menu.xml"/>
-->
<mapper class="com.demo.mapper.MenuMapper"/>
<mapper class="com.demo.mapper.UserMapper"/>
<mapper class="com.demo.mapper.ProductMapper"/>
</mappers>
</configuration>

  3.5、测试注解方式TestMyBatis

package com.demo;

import java.io.IOException;
import java.io.InputStream;
import java.util.List; 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 com.demo.mapper.ProductMapper;
import com.demo.pojo.Product; public class TestMybatis { public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
//加载基于注解方式的映射文件
UserMapper mapper = session.getMapper(UserMapper.class); List<User> list= mapper.list();
for (User user : list) {
System.out.println(user.getName());
List<Menu> menu_list=user.getMenu();
if(menu_list!=null){
for(Menu menu:menu_list){
System.out.println(menu.getProduct().getId(),menu.getProduct().getName(),menu.getProduct().getPrice(),menu.getNumber());
}
}
} session.commit();
session.close(); }
}