九、持久层框架(MyBatis)

一、基于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;
    }
}
View Code

  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>
View Code

  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>
View Code

  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();
    }
}
View Code

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;
    }
}
View Code

  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>
View Code

  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;
    }

}
View Code

  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;
    }
    
}
View Code

  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>
View Code

  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>
View Code

  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>
View Code

  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();
}
View Code

  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);
    
}
View Code

  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>
View Code

  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();
  
    }
}    
View Code

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);
    
}
View Code

  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();
}
View Code

  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 + "	对应的分类是:	" + product.getCategory().getName());
        }

        session.commit();
        session.close();
  
    }
}
View Code

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);
}
View Code

  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();
}
View Code

  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);
}
View Code

  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>
View Code

  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();
  
    }
}
View Code
原文地址:https://www.cnblogs.com/drq1/p/8532951.html