一、基于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(); } }