数据表的sql下载 密码: xjjw
先来看一部分代码
Public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mysql");
//定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
//获取预处理statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
上面代码有如下几个问题:
Mybatis的运行环境(jar包)
log4j.properties
# Global logging configuration
# 开发环境下,日志级别要设置成DEBUG或者ERROR
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SqlMapConfig.xml
<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?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="sqlmap/User.xml"/>
mappers>
configuration>
User.xml
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="com.nuc.mybatis.po.User">
select * from user where id=#{VALUE }
select>
<select id="findUserByName" parameterType="java.lang.String" resultType="com.nuc.mybatis.po.User">
select * from user WHERE username LIKE '%${value}%'
select>
<insert id="insertUser" parameterType="com.nuc.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
selectKey>
insert into user (username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
insert>
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
delete>
<update id="updateUser" parameterType="com.nuc.mybatis.po.User">
UPDATE user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
update>
mapper>
User.java
package com.nuc.mybatis.po;
import java.util.Date;
public class User {
//用户po
//属性名和数据库字段名对应
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
MybatisFirst.java
package com.nuc.mybatis.first;
import com.nuc.mybatis.po.User;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybatisFirst {
//根据id查询用户信息,得到一条记录
@Test
public void findUserByIdTest() throws IOException {
//mybatis配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SqlSession操作数据库
//第一个参数:映射文件中的statement的id,等于namespace+"."+statement的id
//第二个参数:指定和映射文件中所匹配的所有parameterType的类型
//sqlSession.selectOne()的结果是映射文件中所匹配的resultType类型的对象
User user = sqlSession.selectOne("test.findUserById",1);
System.out.println(user);
//释放资源
sqlSession.close();
}
//根据用户名称查询用户列表
@Test
public void findUserByName() throws IOException {
//mybatis配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
List list= sqlSession.selectList("test.findUserByName","小明");
System.out.println(list);
sqlSession.close();
}
/*
小结:
selectOne和selectList:
selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。
selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。
如果使用selectOne报错:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4
*/
@Test
public void insertUserTest() throws IOException {
//mybatis配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("宋江涛");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("山西");
//list中的user和映射文件User.xml中的resultType的类型一直
sqlSession.insert("test.insertUser",user);
//提交事务
sqlSession.commit();
//获取主键
System.out.println(user.getId());
sqlSession.close();
}
//删除用户
@Test
public void deleteUserTest() throws IOException {
//mybatis配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//list中的user和映射文件User.xml中的resultType的类型一直
sqlSession.delete("test.deleteUser",30);
//提交事务
sqlSession.commit();
sqlSession.close();
}
//更新用户
@Test
public void updateUserTest() throws IOException {
//mybatis配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(27);
user.setUsername("宋江涛new2");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("山西太原new");
//list中的user和映射文件User.xml中的resultType的类型一直
sqlSession.update("test.updateUser",user);
//提交事务
sqlSession.commit();
sqlSession.close();
}
}
数据库的设计图
部分测试结果
jdbc的测试程序,前面已经沾过。
重点内容在代码的注释中均已说明
mybatis和hibernate本质区别和应用场景
hibernate:是一个标准ORM框架(对象关系映射)。入门门槛较高的,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的。
mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。
企业进行技术选型,以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。
原始dao开发方法(程序需要编写dao接口和dao实现类)(掌握)
UserDao.java
package com.nuc.mybatis.dao;
import com.nuc.mybatis.po.User;
public interface UserDao {
//dao原始开发
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//添加用户
public void insertUser(User user) throws Exception;
//删除用户
public void deleteUser(int id) throws Exception;
}
UserDaoImpl.java
package com.nuc.mybatis.dao;
import com.nuc.mybatis.po.User;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSession;
public class UserDaoImpl implements UserDao {
//原生态的dao
//需要向dao实现类里注入SqlSessionFactory
//通过构造方法
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.sqlSessionFactory=sqlSessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById",id);
sqlSession.close();
return user;
}
@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.insertUser",user);
sqlSession.commit();
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.deleteUser",id);
sqlSession.commit();
sqlSession.close();
}
}
UserDaoImplTest.java
package com.nuc.mybatis.test;
import com.nuc.mybatis.mapper.UserMapper;
import com.nuc.mybatis.po.User;
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 org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserMapperTest {
//原始dao的测试
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception{
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper的对象,mybatis自动调用
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
}
@Test
public void testFindUserByName() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper的对象,mybatis自动调用
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List list= userMapper.findUserByName("宋江涛");
System.out.println(list);
}
//其他的测试,可以照猫画虎
}
Mybatis的mapper接口(相当于dao接口)代理开发方法(掌握)
根据上面的结构图创建相应文件,源码如下:
UserMapper.java
package com.nuc.mybatis.mapper;
import com.nuc.mybatis.po.User;
import java.util.List;
public interface UserMapper {
//mapper代理开发和dao开发对比
// mapper接口,相当于dao接口,mybatis可以自动生成mapper接口实现类的代理对象
//根据id查询用户信息
public User findUserById(int id) throws Exception;
//根据用户名查询用户列表
public ListfindUserByName(String name) throws Exception;
//添加用户
public void insertUser(User user) throws Exception;
//删除用户
public void deleteUser(int id) throws Exception;
}
UserMapper.xml
<mapper namespace="com.nuc.mybatis.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="com.nuc.mybatis.po.User">
select * from user where id=#{VALUE }
select>
<select id="findUserByName" parameterType="java.lang.String" resultType="com.nuc.mybatis.po.User">
select * from user WHERE username LIKE '%${value}%'
select>
<insert id="insertUser" parameterType="com.nuc.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
selectKey>
insert into user (username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
insert>
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
delete>
<update id="updateUser" parameterType="com.nuc.mybatis.po.User">
UPDATE user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
update>
mapper>
在测试之前需要在SqlMapConfig.xml中加载mapper.xml这个映射文件
UserMapperTest.java
package com.nuc.mybatis.test;
import com.nuc.mybatis.mapper.UserMapper;
import com.nuc.mybatis.po.User;
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 org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserMapperTest {
//原始mapper的测试
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception{
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper的对象,mybatis自动调用
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
}
@Test
public void testFindUserByName() throws Exception{
//返回列表测试
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper的对象,mybatis自动调用
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List list= userMapper.findUserByName("宋江涛");
System.out.println(list);
}
}
mapper开发
mapper开发只需要遵守几个规范即可
其实,以上开发规范主要是对下边的代码进行统一生成:
User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);
。。。。
mapper接口方法参数只能有一个是否影响系统 开发?mapper接口方法参数只能有一个,系统是否不利于扩展维护?
注意:持久层方法的参数可以包装类型、map。。。,service方法中建议不要使用包装类型(不利于业务层的可扩展)。
properties(属性)
特性: MyBatis 将按照下面的顺序来加载属性:
建议:
Mybatis输入映射(掌握)
package com.nuc.mybatis.po;
public class UserCustom extends User {
//可扩展用户信息
}
UserQueryVo.java
package com.nuc.mybatis.po;
public class UserQueryVo {
//这里包装所需的查询条件
//用户查询条件
private UserCustom userCustom;
public UserCustom getUserCustom() {
return userCustom;
}
public void setUserCustom(UserCustom userCustom) {
this.userCustom = userCustom;
}
//可包装其他的查询条件,订单,商品。。。
}
UserMapper.xml中配置新的查询
UserMapperTest.java中新增测试
测试结果
Mybatis输出映射(掌握)
在上面的输入中,属于每一列都成功映射
当我们修改查询语句为:
其中id,起了别名叫做id_
测试结果:
很明显,由于查询条件,生日和地址为空,由于id的映射失败,导致查询id失败,只有sex一列映射成功,故查询成功(1代表男,2代表女)
如法炮制,对mapper.xml编辑和mapper.java编辑
测试代码(复制修改)
测试结果
总结:查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。
2.resultType的输出pojo对象和pojo列表
二、resultMap
<select id="findUserCount" parameterType="com.nuc.mybatis.po.UserQueryVo"
resultType="int">
select count(*) from user
<where>
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex=#{userCustom.sex}
if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username=#{userCustom.username}
if>
if>
where>
select>
<sql id="Query_user">
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex=#{userCustom.sex}
if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username=#{userCustom.username}
if>
if>
sql>
<select id="findUserCount" parameterType="com.nuc.mybatis.po.UserQueryVo"
resultType="int">
select count(*) from user
<where>
<include refid="Query_user"/>
where>
select>
<sql id="Query_user">
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex=#{userCustom.sex}
if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username=#{userCustom.username}
if>
if>
<if test="ids!=null">
<foreach collection="ids" item="user_id" open="and(" close=")" separator="OR">
id=#{user_id}
foreach>
if>
sql>
// 用户综合查询总数
@Test
public void testFindUser() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper的对象,mybatisCount自动调用
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建包对象,设置查询条件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
// 由于这里使用动态sql所以不设置某个值,就不会拼接在sql语句中
// userCustom.setSex("1");
userCustom.setUsername("小明");
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(10);
list.add(16);
userQueryVo.setIds(list);
userQueryVo.setUserCustom(userCustom);
int count= userMapper.findUserCount(userQueryVo);
System.out.println(count);
}
数据模型分析思路
下来拿之前的数据库的表为例,具体字段不作说明
根据上面的步骤。
第一步:每张表记录的数据内容
第二步:每张表重要的字段设置
第三步:数据库级别表与表之间的关系
先分析数据库级别之间有关系的表之间的业务关系:
usre和orders:
orders和orderdetail:
第四步:表与表之间的业务关系
一对一
需求:查询订单信息,关联查询创建订单的用户信息
分析:
由于orders表中有一个外键(user_id),通过外键关联查询用户表只能查询出一条记录,可以使用内链接。
SELECT
orders.*,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
WHERE orders.user_id = user.id
Orders.java
package com.nuc.mybatis.po;
import java.util.Date;
import java.util.List;
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
//用户信息
private User user;
//订单明细
private List orderdetails;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number == null ? null : number.trim();
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note == null ? null : note.trim();
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List getOrderdetails() {
return orderdetails;
}
public void setOrderdetails(List orderdetails) {
this.orderdetails = orderdetails;
}
}
OrdersCustom .java
package com.nuc.mybatis.po;
public class OrdersCustom extends Orders {
private String username;
private String sex;
private String address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
OrdersMapperCustom.java
package com.nuc.mybatis.mapper;
import java.util.List;
public interface OrdersMapperCustom {
public List findOrdersUser()throws Exception;
}
OrdersMapperCustom .xml
<mapper namespace="com.nuc.mybatis.mapper.OrdersMapperCustom">
<select id="findOrdersUser" resultType="com.nuc.mybatis.po.OrdersCustom">
SELECT
orders.*,
user.username,
user.sex,
user.address
FROM
orders,
user
WHERE orders.user_id = user.id
select>
mapper>
OrdersMapperTest.java
package com.nuc.mybatis.test;
import com.nuc.mybatis.mapper.OrdersMapperCustom;
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 org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class OrdersMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception{
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindOrdersUser() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 调用maper的方法
List list = ordersMapperCustom.findOrdersUser();
System.out.println(list);
sqlSession.close();
}
}
第三步:
<resultMap type="com.nuc.mybatis.po.Orders" id="OrdersUserResultMap">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<association property="user" javaType="com.nuc.mybatis.po.User">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
association>
resultMap>
<select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
SELECT
orders.*,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
WHERE orders.user_id = user.id
select>
第四步
//查询订单关联查询用户使用resultMap
public List findOrdersUserResultMap()throws Exception;
测试
@Test
public void testFindOrdersResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 调用maper的方法
List list = ordersMapperCustom.findOrdersUserResultMap();
System.out.println(list);
sqlSession.close();
}
总结
resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType。
resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。resultMap可以实现延迟加载,resultType无法实现延迟加载。
一对多
添加属性在之前已经实现,且注释。
只需要配置xml文件和接口,写一个测试类即可
<resultMap type="com.nuc.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">
<collection property="orderdetails" ofType="com.nuc.mybatis.po.Orderdetail">
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
collection>
resultMap>
<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id
FROM
orders,
USER,
orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
select>
//查询订单(关联用户)及订单明细
public List findOrdersAndOrderDetailResultMap() throws Exception;
@Test
public void testfindOrdersAndOrderDetailResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 调用maper的方法
List list = ordersMapperCustom.findOrdersAndOrderDetailResultMap();
System.out.println(list);
sqlSession.close();
}
总结:
多对多
映射思路
mapper.xml
<resultMap type="com.nuc.mybatis.po.User" id="UserAndItemsResultMap">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<collection property="ordersList" ofType="com.nuc.mybatis.po.Orders">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<collection property="orderdetails" ofType="com.nuc.mybatis.po.Orderdetail">
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
<association property="items" javaType="com.nuc.mybatis.po.Items">
<id column="items_id" property="id"/>
<result column="items_name" property="name"/>
<result column="items_detail" property="detail"/>
<result column="items_price" property="price"/>
association>
collection>
collection>
resultMap>
//查询用户购买商品信息
public List findUserAndItemsResultMap()throws Exception;
多对多查询总结
总结:使用resultMap是针对那些对查询结果映射有特殊要求的功能,比如特殊要求映射成list中包括 多个list
resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。
延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。
不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??
总之:使用延迟加载方法,先去查询简单的sql(最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。
一级缓存
测试:
//mybatis默认支持一级缓存,不需要在配置文件去配置。
@Test
public void testCache1() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();//创建代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//下边查询使用一个SqlSession
//第一次发起请求,查询id为1的用户
User user1 = userMapper.findUserById(1);
System.out.println(user1);
// 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
//更新user1的信息
user1.setUsername("测试用户22");
userMapper.updateUser(user1);
//执行commit操作去清空缓存
sqlSession.commit();
//第二次发起请求,查询id为1的用户
User user2 = userMapper.findUserById(1);
System.out.println(user2);
sqlSession.close();
}
一级缓存应用
正式开发,是将mybatis和spring进行整合开发,事务控制在service中。
一个service方法中包括 很多mapper方法调用。
service{
//开始执行时,开启事务,创建SqlSession对象
//第一次调用mapper的方法findUserById(1)
//第二次调用mapper的方法findUserById(1),从一级缓存中取数据
//方法结束,sqlSession关闭
}
如果是执行两个service调用查询相同 的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。
二级缓存
// 二级缓存测试
@Test
public void testCache2() throws Exception {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
// 创建代理对象
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
// 第一次发起请求,查询id为1的用户
User user1 = userMapper1.findUserById(1);
System.out.println(user1);
//这里执行关闭操作,将sqlsession中的数据写到二级缓存区域
sqlSession1.close();
//使用sqlSession3执行commit()操作
UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
User user = userMapper3.findUserById(1);
user.setUsername("张明明");
userMapper3.updateUser(user);
//执行提交,清空UserMapper下边的二级缓存
sqlSession3.commit();
sqlSession3.close();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
// 第二次发起请求,查询id为1的用户
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
}
useCache配置
总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。
刷新缓存(就是清空缓存)
总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。
mybatis整合ehcache
mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合。
整合方法(掌握):
在config目录下加入ehcache的配置文件
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
defaultCache>
ehcache>
二级缓存应用场景:
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
二级缓存局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
mybatis的项目源码密码: b54x
mybatis的文档教程密码: pbvf
mybatis+springMVC的视频教程mybatis+springMVC