1.ORM框架mybatis的基本介绍(包括配置文件):
ORM可以解决数据库与程序间的异构性,比如在Java中我们使用String表示字符串,而Oracle中可使用varchar2,MySQL中可使用varchar,SQLServer可使用nvarchar。
ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射。
没有ORM时我们是这样完成对象与关系数据库之间的映射的:
//将执行的sqlString sql = "SELECT name, id, age, password FROM users";//创建命令对象preparedStatement = connection.prepareStatement(sql);//执行并获得结果集resultSet = preparedStatement.executeQuery();//遍历结果集,将数据库中的数据转换成Java中的对象while(resultSet.next()){String name = resultSet.getString("name");int id = resultSet.getInt("id");int age = resultSet.getInt("age");String password = resultSet.getString("password");User entity= new User(name,id,age,password);Users.add(entity);}
这种写法的不足:
- 原生的jdbc会频繁的创建链接和释放资源,会增加数据库的链接压力
解决方法:使用连接池,用连接池来管理数据库的链接和释放资源。 - 原生的jdbc的sql语句是写在java代码中的,这种方式属于硬编码,不利于sql代码的维护。
解决方法:mybatis框架将sql语句提取到xml配置文件中,每一次修改sql语句,只需要修改配置文件中的语句即可,和代码无关 - 原生的jdbc预编译对象中的?也属于硬编码
解决方法:mybatis框架将视线关系对象映射,mybatis存在输入对象映射和输出对象映射。
原生的jdbc:
public class Demo{private static String driver = "com.mysql.jdbc.Driver";private static String url = "jdbc:mysql://localhost:3306/db_shop";private static String username = "root";private static String password = "";static{//加载驱动Class.forName(driver);}public static void main(String[] args){try{Connection conn = ManagerDriver.getConnection(url,username,password);String sql = "select * from student where id = ?";PreparedStatement ps = conn.prepareStatement(sql);ps.setInt(1,user.getInt());ResultSet rs = ps.executeQuery();while(rs.next()){}rs.close();ps.close();conn.close();}catch(Exception e){}}}
mybatis概念:
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
案例代码:查询
这是mybatis基本的框架
编写sqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 使用mybatis需要的数据源和事务配置,后续如果整合spring之后,将不再需要 --><environments default="development"><!-- 配置数据源和事务 --><environment id="development"><!-- 配置事务管理,将事务管理交给mybatis管理 --><transactionManager type="JDBC" /><!-- 配置数据源 --><dataSource type="POOLED"><property name = "driver" value = "com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value=""/></dataSource></environment></environments><!-- 加载**.xml配置文件 --><mappers><mapper resource="Food.xml"/></mappers></configuration>
编写log4j.properties标签
# Global logging configurationlog4j.rootLogger=DEBUG, stdout# MyBatis logging configuration...log4j.logger.org.mybatis.example.BlogMapper=TRACE# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
编写失血模型对象:food模型
package model;/*** @ClassName: food.java* @Description: 该类的功能描述* @version: v1.0.0* @author: 169986432* @date: 2020年10月11日 下午2:38:05*/public class Food {private int id;private String last_name;private String gender;private String email;public Food() {super();}public Food(int id, String last_name, String gender, String email) {super();this.id = id;this.last_name = last_name;this.gender = gender;this.email = email;}/*** @return the id*/public int getId() {return id;}/*** @param id the id to set*/public void setId(int id) {this.id = id;}/*** @return the last_name*/public String getLast_name() {return last_name;}/*** @param last_name the last_name to set*/public void setLast_name(String last_name) {this.last_name = last_name;}/*** @return the gender*/public String getGender() {return gender;}/*** @param gender the gender to set*/public void setGender(String gender) {this.gender = gender;}/*** @return the email*/public String getEmail() {return email;}/*** @param email the email to set*/public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "Food [id=" + id + ", last_name=" + last_name + ", gender=" + gender + ", email=" + email + "]";}}
编写单个映射关系的sql.xml:Food.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="test"><select id="foodAll" parameterType="java.lang.Integer" resultType="model.Food">SELECT * FROM food WHERE last_anme= #{value}</select></mapper>
编写dao接口:查询的接口
public interface FoodDao {public Food queryProductById(String last_name) throws Exception;}
编写dao接口的实现类:FoodImpl实现类
public class FoodDaoImpl implements FoodDao {//声明一个会话工厂private SqlSessionFactory factory;//由构造方法进行创建对象赋值public FoodDaoImpl(SqlSessionFactory factory) {this.factory = factory;}@Overridepublic Food queryProductById(String last_name) throws Exception {//开启会话SqlSession sqlSession = factory.openSession();Food prod = sqlSession.selectOne("test.foodAll", last_name);//关闭会话sqlSession.close();return prod;}}
测试类:测试
public class Test {//创建dao的实现类public static void main(String[] args) throws Exception{String path = "SqlMapConfig.xml";InputStream config = Resources.getResourceAsStream(path);//创建一个会话工厂SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config);testQuery1(factory);}public static void testQuery1(SqlSessionFactory factory) throws Exception {FoodDao dao = new FoodDaoImpl(factory);int id = 1;Food food=dao.queryProductById("张三");System.out.println(food);}}
mybatis的最简单的增,删,改,查
思路:
1.导入jr包,创建xml里面配置增,删,改。查的sql语句
2.创建xml文件在SqlMapConfig.xml文件中进行配置加载
3.创建一个失血模型要跟数据库的字段一致
4.创建一个接口,接口当中包含5个方法,两个查询、增、删、改的方法。只有定义。
5.创建实现类,实现定义的接口,按照规定进行重写方法。声明工厂类对象,该对象由该类的构造方法进行赋值。
6.编写测试类,在测试类中,创建工厂对象,传递给dao的实现类。
代码:
编写xml:food.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="first"><!-- 根据id查询 --><select id="queryId" parameterType="java.lang.Integer" resultType="model.Food">SELECT * FROM t_product WHERE p_id = #{p_id}</select><!-- 根据名称模糊查询,返回多条结果集 --><select id="queryName" parameterType="java.lang.String" resultType="model.Food">SELECT * FROM t_product WHERE name like "%${value}%"</select><!-- 新增一条数据 --><insert id="insert" parameterType="model.Food">INSERT INTO t_product(name,p_number,price) value(#{name},#{p_number},#{price})</insert><!-- 根据id值更新 --><update id="update" parameterType="model.Food">UPDATE t_product SET name = #{name} WHERE p_id = #{p_id}</update><!-- 根据id删除 --><delete id="delete" parameterType="java.lang.Integer">DELETE FROM t_product WHERE p_id = #{p_id}</delete></mapper>
编写xml:加载food。xml
编写接口增,删,改,查
public interface FoodDao {public Food queryId(int id) throws Exception;public List<Food> queryName(String name) throws Exception;public Food insert(Food product) throws Exception;public int update(Food product) throws Exception;public int delete(int id) throws Exception;}
编写接口的实现类
public class FoodDaoImpl implements FoodDao {//声明一个会话工厂private SqlSessionFactory factory;//由构造方法进行创建对象赋值public FoodDaoImpl(SqlSessionFactory factory) {this.factory = factory;}@Overridepublic Food queryId(int id) throws Exception {SqlSession sqlSession = factory.openSession();Food food= sqlSession.selectOne("first.queryId", id);sqlSession.close();return food;}@Overridepublic List<Food> queryName(String name) throws Exception {SqlSession sqlSession = factory.openSession();List<Food> list = sqlSession.selectList("first.queryName", name);sqlSession.close();return list;}@Overridepublic Food insert(Food food) throws Exception {SqlSession sqlSession = factory.openSession();int row = sqlSession.insert("first.insert", food);sqlSession.commit();sqlSession.close();return food;}@Overridepublic int update(Food food) throws Exception {SqlSession sqlSession = factory.openSession();int row = sqlSession.update("first.update", food);sqlSession.commit();sqlSession.close();return row;}@Overridepublic int delete(int id) throws Exception {SqlSession sqlSession = factory.openSession();int row = sqlSession.delete("first.delete", id);sqlSession.commit();sqlSession.close();return row;}}
测试类:测试
public class Test {//创建dao的实现类public static void main(String[] args) throws Exception{String path = "SqlMapConfig.xml";InputStream config = Resources.getResourceAsStream(path);//创建一个会话工厂SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config);// testQuery1(factory);// testQuery2(factory);testQuery3(factory);}public static void testQuery1(SqlSessionFactory factory) throws Exception {FoodDao dao = new FoodDaoImpl(factory);int id = 1;Food food = dao.queryId(id);System.out.println(food);}public static void testQuery2(SqlSessionFactory factory) throws Exception {FoodDao dao = new FoodDaoImpl(factory);String name = "牛奶";List<Food> list = dao.queryName(name);System.out.println(list);}public static void testQuery3(SqlSessionFactory factory) throws Exception {SqlSession session = factory.openSession();Food food=session.getMapper(Food.class);Food food1=new Food();food1.setP_id(7);food1.setName("阿萨姆奶茶");food1.setP_number(788);food1.setPrice(90);food1.setAdd_time("2020-09-23 17:59:46.0");}}
mapper代理的方式进行讲解增、删、改、查(重点)
配置xml文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><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/mybatis"/><property name="username" value="root"/><property name="password" value=""/></dataSource></environment></environments><!-- 配置sql语句 的那个mapper配置文件 --><mappers><mapper resource="com/dao/UserMapper.xml"/></mappers></configuration>
Mapper代码:
public interface UserMapper {// 保存public int save(Food Food);// 更新public intupdate(Food Food);// 根据id删除public int deleteId(int id);// 根据id搜索public User findId(int id);// 搜索全部public List<User> findFood();}
配置FoodMapper.xml代码:
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.dao.UserMapper"><!-- public Integer save(Food FoodUser user); --><insert id="saveUser" parameterType="com.pojo.Food">insert into t_user(`last_name`,`sex`) values(#{lastName},#{sex})</insert><!-- public Integer updateUser(Food Food); --><update id="updateUser" parameterType="com.pojo.Food">update t_user set last_name = #{lastName} , sex = #{sex} where id = #{id}</update><!-- public Integer deleteUserById(Integer id); --><delete id="deleteUserById">delete from t_user where id = #{id}</delete><!-- public User findUserById(Integer id); --><select id="findUserById" resultType="com.pojo.Food">select id,last_name lastName,sex from t_user where id = #{id}</select><!-- public List<User> findUsers(); --><select id="findUsers" resultType="com.pojo.Food">select id,last_name lastName,sex from t_user</select></mapper>
测试类:
public class FoodMapperTest {static SqlSessionFactory sqlSessionFactory;@BeforeClasspublic static void setUpBeforeClass() throws Exception {String url = "mybatis-config.xml";// 读取配置文件InputStream inputStream = Resources.getResourceAsStream(url);// 创建SqlSessionFactory对象sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void testSave() {SqlSession session = sqlSessionFactory.openSession();try {UserMapper userMapper = session.getMapper(UserMapper.class);User user = new User(0, "ddddd", 1);userMapper.saveUser(user);session.commit();System.out.println(user);} finally {session.close();}}@Testpublic void testUpdateUser() {SqlSession session = sqlSessionFactory.openSession();try {UserMapper userMapper = session.getMapper(UserMapper.class);User user = new User(4, "eeeee", 1);userMapper.updateUser(user);session.commit();} finally {session.close();}}@Testpublic void testDeleteById() {SqlSession session = sqlSessionFactory.openSession();try {UserMapper userMapper = session.getMapper(UserMapper.class);userMapper.deleteUserById(4);session.commit();} finally {session.close();}}@Testpublic void testFindById() {SqlSession session = sqlSessionFactory.openSession();try {UserMapper userMapper = session.getMapper(UserMapper.class);System.out.println(userMapper.findUserById(1));} finally {session.close();}}@Testpublic void testFind() {SqlSession session = sqlSessionFactory.openSession();try {UserMapper userMapper = session.getMapper(UserMapper.class);System.out.println(userMapper.findUsers());} finally {session.close();}}
效果:
别名和mapper映射详解
设置别名:
1.设置别名位置是在SqlMapConfig.xml配置文件中
<!-- 设置一个别名 --><typeAliases><!--type: 要设置的model全路径名alias:取的别名--><typeAlias type="com.woniuxy.mall.model.User" alias="user"/></typeAliases>
2.推荐使用批量设置别名,扫描model包
<typeAliases><!--name:包名--><package name="com.woniuxy.mall.model"/></typeAliases>
Mapper映射关系配置
以mapper.xml配置文件的方式
以配置Mapper接口的方式进行配置
<!-- 加载mapper.xml文件 --><mappers><!--class:对应接口的全路径名要求:对应的mapper.java接口文件和mapper.xml配置文件必须放在同一个包下面。mapper.java接口文件和mapper.xml配置文件的名字必须要一致。--><mapper class="mapper.FoodMapper"/></mappers>
以扫描包的形式进行配置
<!-- 加载mapper.xml文件 --><mappers><!--name:mapper接口的包名规则同上。--><package name="mapper"/></mappers>
自定义的POJO类
自定义POJO类,一般指的是高级查询,在想要的数据和传入的条件不再一张表中,通过表所创建的失血模型model已经不能够满足传入参数的需求了,这个时候,就需要使用自定义的POJO类
因为一个失血模型已经不能够满足查询输入参数的要求了,所以进行扩展,创建一个UserCustom类,里面包含user对象声明和userInfo对象声明
Customer 实体类:
public class Customer {private List<Orders> orders; // 关联多个订单private Integer id;private String name;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<Orders> getOrders() {return orders;}public void setOrders(List<Orders> orders) {this.orders = orders;}}
Orders 实体类:
public class Orders {private Integer id;private String sn; // 订单编号private String remark; // 订单描述public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getSn() {return sn;}public void setSn(String sn) {this.sn = sn;}public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}
创建 CustomerMapper.xml 映射文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="yeepay.payplus.mapper.CustomerMapper"><resultMap type="yeepay.payplus.domain.Customer" id="customerRM"><id property="id" column="ID"/><result property="name" column="NAME"/></resultMap><!-- 配置关联关系 1:N --><resultMap type="yeepay.payplus.domain.Customer" id="customerOrdersRM" extends="customerRM"><!-- 配置多的(N),property 属性就是实体中的 List 对象属性名称,ofType 属性就是集合元素的类型 --><collection property="orders" ofType="yeepay.payplus.domain.Orders"><id property="id" column="ID"/><result property="sn" column="SN"/><result property="remark" column="REMARK"/></collection></resultMap><!-- 查询,关联关系 Map 作为查询条件 --><select id="find" parameterType="map" resultMap="customerOrdersRM">SELECTc.name,o.sn,o.remarkFROM(SELECT id,name FROM customer) cLEFT JOIN(SELECT id,sn,remark,customer_id FROM orders) oON c.id = o.customer_idWHERE c.name = #{customerName}</select></mapper>
sqlMapConfig.xml 配置文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 赋别名 --><typeAliases><typeAlias type="yeepay.payplus.domain.Person" alias="Person"/></typeAliases><!-- 配置开发环境,可以配置多个,在具体用时再做切换 --><environments default=""><environment id="test"><transactionManager type="JDBC"></transactionManager> <!-- 事务管理类型:JDBC、MANAGED --><dataSource type="POOLED"> <!-- 数据源类型:POOLED、UNPOOLED、JNDI --><property name="driver" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf-8" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment></environments><!-- 加载映射文件 mapper --><mappers><!-- 路径用 斜线(/) 分割,而不是用 点(.) --><mapper resource="yeepay/payplus/mapper/UserMapper.xml"/><mapper resource="yeepay/payplus/mapper/CustomerMapper.xml"/></mappers></configuration>
创建 CeshiCustomer 测试类
public class CeshiCustomer {@Testpublic void testFind() throws IOException {/*** 1、获得 SqlSessionFactory* 2、获得 SqlSession* 3、调用在 mapper 文件中配置的 SQL 语句*/String resource = "sqlMapConfig.xml"; // 定位核心配置文件InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 创建 SqlSessionFactorySqlSession sqlSession = sqlSessionFactory.openSession(); // 获取到 SqlSessionMap map = new HashMap();map.put("customerName", "charies");// 调用 mapper 中的方法:命名空间 + idList<Customer> customerList = sqlSession.selectList("yeepay.payplus.mapper.CustomerMapper.find", map);for (Customer c : customerList) {System.out.println(c);}}
输入映射:目前在mybatis用到的都是parameterType类型,其中可以是简单数据类型,也可以是包装类型(POJO)
parameterType:java.lang.Integer\java.lang.String\POJO模型类。
输出映射
- 输出的类型为POJO包装类(model失血模型),用的是resultType
- 输出的类型为简单数据类型,resultType,要求:查询的结果集必须是一行一列的数据
- 输出类型为resultMap方式,当前的作用,当java中失血模型对象中的字段和数据库中的字段名称不一致的时候,可以使用resultMap方式进行自定义映射关系。
代码:
<resultMap type="User" id="userResult"><!-- id: 用来关联在查询结果集中可以唯一识别一个实体的字段,一般都是主键column:在查询结果集中,能够唯一识别一个实体的字段名property:结果集中的数据和失血模型中对应的属性名。--><id column="id" property="user_id"/><!--result:除了能唯一识别实体字段以外的其他普通字段column:在查询结果集中,数据库的字段名property:结果集中的数据和失血模型中对应的属性名。--><result column="userName" property="user_name"/><result column="pass" property="password"/></resultMap><!-- 查询所有用户 --><select id="queryAllUser" resultMap="userResult">SELECT user_id id,user_name userName,`password` pass FROM t_user</select>
动态sql
<!-- 编写一个sql片段,供以后重复使用sql片段 --><sql id="query_user_info"><if test="user.user_name != null">AND s1.user_name like "%${user.user_name}%"</if><if test="userInfo.gender != null">AND s2.gender = #{userInfo.gender}</if></sql><!-- 使用sql片段 --><select id="queryUserAndInfo" parameterType="com.woniuxy.mall.model.UserCustom" resultType="User">SELECT * FROM t_user as s1 JOIN t_userinfo as s2 on s1.user_id = s2.user_id<where><include refid="query_user_info"></include></where></select>
一对一、一对多、多对多查询
一对一的关系:人与身份证
Idcard 的代码:
public class Idcard {private Integer id;private String code;public day(Integer id, String code) {super();this.id = id;this.code = code;}public day() {super();}/*** @return the id*/public Integer getId() {return id;}/*** @param id the id to set*/public void setId(Integer id) {this.id = id;}/*** @return the code*/public String getCode() {return code;}/*** @param code the code to set*/public void setCode(String code) {this.code = code;}@Overridepublic String toString() {return "day [id=" + id + ", code=" + code + "]";}
Person 的代码:
public class Person {private Integer id;private String name;private Integer age;// 个人身份证关联private Idcard card;// 省略setter和getter方法@Overridepublic String toString() {return "Person[id=" + id + ",name=" + name + ",age=" + age + ",card="+ card + "]";}}
IdCardMapper.xml 的代码:
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.dao.IdCardDao"><select id="selectCodeById" parameterType="Integer" resultType= "com.po.Idcard">select * from idcard where id=#{id}</select></mapper>
PersonMapper.xml 的代码:
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.dao.PersonDao"><!-- 一对一根据id查询个人信息:级联查询的第一种方法(嵌套查询,执行两个SQL语句)--><resultMap type="com.po.Person" id="cardAndPerson1"><id property="id" column="id"/><result property="name" column="name"/><result property="age" column="age"/><!-- 一对一级联查询--><association property="card" column="idcard_id" javaType="com.po.Idcard"select="com.dao.IdCardDao.selectCodeByld"/></resultMap><select id="selectPersonById1" parameterType="Integer" resultMap="cardAndPerson1">select * from person where id=#{id}</select><!--对一根据id查询个人信息:级联查询的第二种方法(嵌套结果,执行一个SQL语句)--><resultMap type="com.po.Person" id="cardAndPerson2"><id property="id" column="id"/><result property="name" column="name"/><result property="age" column="age"/><!-- 一对一级联查询--><association property="card" javaType="com.po.Idcard"><id property="id" column="idcard_id"/><result property="code" column="code"/></association></resultMap><select id="selectPersonById2" parameterType="Integer" resultMap= "cardAndPerson2">select p.*,ic.codefrom person p, idcard icwhere p.idcard_id=ic.id and p.id=#{id}</select><!-- 一对一根据id查询个人信息:连接查询(使用POJO存储结果)--><select id="selectPersonById3" parameterType="Integer" resultType= "com.pojo.SelectPersonById">select p.*,ic.codefrom person p, idcard icwhere p.idcard_id = ic.id and p.id=#{id}</select></mapper>
创建 POJO 类
SelectPersonById 的代码
public class SelectPersonById {private Integer id;private String name;private Integer age;private String code;public day() {super();}public day(Integer id, String name, Integer age, String code) {super();this.id = id;this.name = name;this.age = age;this.code = code;}/*** @return the id*/public Integer getId() {return id;}/*** @param id the id to set*/public void setId(Integer id) {this.id = id;}/*** @return the name*/public String getName() {return name;}/*** @param name the name to set*/public void setName(String name) {this.name = name;}/*** @return the age*/public Integer getAge() {return age;}/*** @param age the age to set*/public void setAge(Integer age) {this.age = age;}/*** @return the code*/public String getCode() {return code;}/*** @param code the code to set*/public void setCode(String code) {this.code = code;}@Overridepublic String toString() {return "day [id=" + id + ", name=" + name + ", age=" + age + ", code=" + code + "]";}
创建数据操作接口:
IdCardDao 的代码
public interface IdCardDao {public Idcard selectCodeById(Integer i);}
PersonDao 的代码
public interface PersonDao {public Person selectPersonById1(Integer id);public Person selectPersonById2(Integer id);public SelectPersonById selectPersonById3(Integer id);}
调用
public class OneToOneController {@Autowiredprivate PersonDao personDao;public void test(){Person p1 = personDao.selectPersonById1(1);System.out.println(p1);System.out.println("=============================");Person p2 = personDao.selectPersonById2(1);System.out.println(p2);System.out.println("=============================");selectPersonById p3 = personDao.selectPersonById3(1);System.out.println(p3);}}
测试:
public class TestOneToOne {public static void main(String[] args) {ApplicationContext appcon = new ClassPathXmlApplicationContext("applicationContext.xml");OneToOneController oto = (OneToOneController)appcon.getBean("oneToOne-Controller");oto.test();}}
一对多关系:一对多级联查询,用户关联的订单
Orders 类的代码:
public class Orders {private Integer id;private String ordersn;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getOrdersn() {return ordersn;}public void setOrdersn(String ordersn) {this.ordersn = ordersn;}@Overridepublic String toString() {return "Orders[id=" + id + ",ordersn=" + ordersn + "]";}}
创建UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.mybatis.mapper.UserMapper"><!-- 一对多 根据uid查询用户及其关联的订单信息:级联查询的第一种方法(嵌套查询) --><resultMap type="com.po.MyUser" id="userAndOrders1"><id property="uid" column="uid" /><result property="uname" column="uname" /><result property="usex" column="usex" /><!-- 一对多级联查询,ofType表示集合中的元素类型,将uid传递给selectOrdersByld --><collection property="ordersList" ofType="com.po.Orders"column="uid" select="com.dao.OrdersDao.selectOrdersByld" /></resultMap><select id="selectUserOrdersById1" parameterType="Integer"resultMap="userAndOrders1">select * from user where uid = #{id}</select><!--对多根据uid查询用户及其关联的订单信息:级联查询的第二种方法(嵌套结果) --><resultMap type="com.po.MyUser" id="userAndOrders2"><id property="uid" column="uid" /><result property="uname" column="uname" /><result property="usex" column="usex" /><!-- 对多级联查询,ofType表示集合中的元素类型 --><collection property="ordersList" ofType="com.po.Orders"><id property="id" column="id" /><result property="ordersn" column="ordersn" /></collection></resultMap><select id="selectUserOrdersById2" parameterType="Integer"resultMap="userAndOrders2">select u.*,o.id, o.ordersn from user u, orders o where u.uid= o.user_id andu.uid=#{id}</select><!-- 一对多 根据uid查询用户及其关联的订单信息:连接查询(使用POJO存储结果) --><select id="selectUserOrdersById3" parameterType="Integer"resultType="com.pojo.SelectUserOrdersById">select u.*, o.id, o.ordersn from user u, orders o whereu.uid = o.user_idand u.uid=#{id}</select></mapper>
创建:OrdersMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.dao.OrdersDao"><!-- 根据用户uid查询订单信息 --><select id="selectOrdersById" resultType="com.po.Orders"parameterType="Integer">select * from orders where user_id=#{id}</select></mapper>
创建 POJO 类
SelectUserOrdersById代码:
public class SelectUserOrdersById {private Integer uid;private String uname;private String usex;private Integer id;private String ordersn;// 省略setter和getter方法@Overridepublic String toString() { // 为了方便查看结果,重写了toString方法return "User[uid=" + uid + ",uname=" + uname + ",usex=" + usex+ ",oid=" + id + ",ordersn=" + ordersn + "]";}}
创建数据操作接口
public interface OrdersDao {public List<Orders> selectOrdersById(Integer uid);}
public interface UserDao {public MyUser selectOrdersById1(Integer uid);public MyUser selectOrdersById2(Integer uid);public List<SelectUserOrdersById> selectOrdersById3(Integer uid);}
调用接口方法
public void test(){//查询一个用户及订单信息MyUser auser1 = userDao.selectUserOrderById1(1);System.out.println(auser1);System.out.println("=============================");MyUser auser2 = userDao.selectUserOrderById2(1);System.out.println(auser2);System.out.println("=============================");List<SelectUserOrdersById> auser3 = userDao.selectUserOrdersById3(1);System.out.println(auser3);System.out.println("=============================");}
测试:
public class TestOneToMore {public static void main(String[] args) {ApplicationContext appcon = new ClassPathXmlApplicationContext("applicationContext.xml");OneToMoreController otm = (OneToMoreController)appcon.getBean("oneToMoreController");otm.test();}}
多对多的关系:订单和商品
Product 的代码:
public class Product {private Integer id;private String name;private Double price;public day() {super();}public day(Integer id, String name, Double price) {super();this.id = id;this.name = name;this.price = price;}/*** @return the id*/public Integer getId() {return id;}/*** @param id the id to set*/public void setId(Integer id) {this.id = id;}/*** @return the name*/public String getName() {return name;}/*** @param name the name to set*/public void setName(String name) {this.name = name;}/*** @return the price*/public Double getPrice() {return price;}/*** @param price the price to set*/public void setPrice(Double price) {this.price = price;}@Overridepublic String toString() {return "day [id=" + id + ", name=" + name + ", price=" + price + "]";}
Orders 的代码:
public class Orders {private Integer id;private String ordersn;public day() {super();}public day(Integer id, String ordersn) {super();this.id = id;this.ordersn = ordersn;}/*** @return the id*/public Integer getId() {return id;}/*** @param id the id to set*/public void setId(Integer id) {this.id = id;}/*** @return the ordersn*/public String getOrdersn() {return ordersn;}/*** @param ordersn the ordersn to set*/public void setOrdersn(String ordersn) {this.ordersn = ordersn;}@Overridepublic String toString() {return "day [id=" + id + ", ordersn=" + ordersn + ", getId()=" + getId() + ", getOrdersn()=" + getOrdersn()+ ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString()+ "]";}
在 Orders 接口中添加以下接口方法:
public List
调用接口方法
public class MoreToMoreController {@Autowiredprivate OrdersDao ordersDao;public void test() {List<Orders> os = ordersDao.selectallOrdersAndProducts();for (Orders orders : os) {System.out.println(orders);}}}
测试:
public class TestMoreToMore {public static void main(String[] args) {ApplicationContext appcon = new ClassPathXmlApplicationContext("applicationContext.xml");MoreToMoreController otm = (MoreToMoreController) appcon.getBean("moreToMoreController");otm.test();}}
延迟加载、一级缓存和二级缓存
什么是延迟加载
resultMap中的association和collection标签具有延迟加载的功能。
延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息。使用关联信息时再去加载关联信息
设置延迟加载
需要在SqlMapConfig.xml文件中,在
lazyLoadingEnabled、aggressiveLazyLoading
<!-- 开启延迟加载 --><settings><!-- lazyLoadingEnabled:延迟加载启动,默认是false --><setting name="lazyLoadingEnabled" value="true"/><!-- aggressiveLazyLoading:积极的懒加载,false的话按需加载,默认是true --><setting name="aggressiveLazyLoading" value="false"/><!-- 开启二级缓存,默认是false --><setting name="cacheEnabled" value="true"/></settings>
Mybatis的一级缓存是指SqlSession。一级缓存的作用域是一个SqlSession。Mybatis默认开启一级缓存。
在同一个SqlSession中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则SqlSession的缓存清空。
Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。
在同一个namespace下的mapper文件中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则二级缓存清空。
一级缓存:

二级缓存:

