阶段4任务:开发Mapper接口和Mapper.xml
阶段5任务:开发和Mapper接口相映射的MapperBean
(1)Mapper接口
package com.li.mapper;
import com.li.entity.Monster;
/**
* @author 李
* @version 1.0
* MonsterMapper:声明对数据库的crud方法
*/
public interface MonsterMapper {
//查询方法
public Monster getMonsterById(Integer id);
}
(2)Mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="com.li.mapper.MonsterMapper">
<!--实现配置接口方法getMonsterById-->
<select id="getMonsterById" resultType="com.li.entity.Monster">
select * from monster where id = ?
</select>
</mapper>
(3)Function.java,用于记录Mapper.xml文件实现的方法信息
package com.li.limybatis.config;
import lombok.Getter;
import lombok.Setter;
/**
* @author 李
* @version 1.0
* Function:记录对应 Mapper.xml的方法信息
*/
@Getter
@Setter
@ToString
public class Function {
private String sqlType;//sql类型,如select,update,insert,delete
private String funcName;//方法名
private String sql;//执行的sql语句
private Object resultType;//返回类型
private String parameterType;//参数类型
}
(4)MapperBean.java,作用是读取Mapper接口对应的Mapper.xml,将该xml文件方法信息封装到MapperBean中。
package com.li.limybatis.config;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* @author 李
* @version 1.0
* MapperBean:将我们的Mapper信息,进行封装
*/
@Setter
@Getter
@ToString
public class MapperBean {
private String interfaceName;//接口名
//接口下的所有方法
public List<Function> functions;
}
阶段6任务:在MyConfiguration中读取xxMapper.xml,能够创建MapperBean对象
(1)修改 MyConfiguration.java,添加 readMapper() 方法
/**
* 读取xxMapper.xml,创建MapperBean对象
* @param path xml的路径+文件名,从类的加载路径开始计算,若xml文件放在resource目录下,直接传入文件名即可
* @return 返回MapperBean对象
*/
public MapperBean readMapper(String path) {
MapperBean mapperBean = new MapperBean();
try {
//获取到mapper.xml文件对应的InputStream
InputStream stream = loader.getResourceAsStream(path);
SAXReader reader = new SAXReader();
//获取到xml文件对应的document
Document document = reader.read(stream);
//得到xml的根节点
Element root = document.getRootElement();
//获取到 namespace
String namespace = root.attributeValue("namespace").trim();
//设置mapperBean的属性interfaceName
mapperBean.setInterfaceName(namespace);
//遍历获取root的子节点-生成 Function
Iterator rootIterator = root.elementIterator();
//保存接口下的所有方法信息
List<Function> list = new ArrayList<>();
while (rootIterator.hasNext()) {
//取出一个子元素
/**
* <select id="getMonsterById" resultType="com.li.entity.Monster">
* select * from monster where id = ?
* </select>
*/
Element e = (Element) rootIterator.next();
Function function = new Function();
String sqlType = e.getName().trim();
String funcName = e.attributeValue("id").trim();
//这里的resultType是返回类型的全路径-全类名
String resultType = e.attributeValue("resultType").trim();
String sql = e.getText().trim();
//将信息封装到 function对象中
function.setSql(sql);
function.setFuncName(funcName);
function.setSqlType(sqlType);
//这里的function.resultType应该为Object类型
//因此使用反射生成对象,再放入function中
Object instance = Class.forName(resultType).newInstance();
function.setResultType(instance);
//将封装好的function对象放到list中
list.add(function);
}
mapperBean.setFunctions(list);
} catch (Exception e) {
e.printStackTrace();
}
return mapperBean;
}
(2)测试
@Test
public void readMapper() {
MyConfiguration myConfiguration = new MyConfiguration();
MapperBean mapperBean = myConfiguration.readMapper("MonsterMapper.xml");
System.out.println("mapperBean=" + mapperBean);
}
测试结果:
mapperBean=MapperBean(interfaceName=com.li.mapper.MonsterMapper, functions=[Function(sqlType=select, funcName=getMonsterById, sql=select * from monster where id = ?, resultType=Monster(id=null, age=null, name=null, email=null, birthday=null, salary=0.0, gender=null), parameterType=null)])
阶段7任务:实现动态代理Mapper的方法-动态代理生成Mapper对象,调用MyExecutor方法
(1)MyMapperProxy.java
package com.li.limybatis.sqlsession;
import com.li.limybatis.config.Function;
import com.li.limybatis.config.MapperBean;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
/**
* @author 李
* @version 1.0
* MyMapperProxy:动态代理生成 Mapper对象,调用 MyExecutor方法
*/
public class MyMapperProxy implements InvocationHandler {
private MySqlSession mySqlSession;
private String mapperFile;
private MyConfiguration myConfiguration;
//构造器
public MyMapperProxy(MySqlSession mySqlSession, MyConfiguration myConfiguration, Class clazz) {
this.mySqlSession = mySqlSession;
this.myConfiguration = myConfiguration;
this.mapperFile = clazz.getSimpleName() + ".xml";
}
//当执行Mapper接口的代理对象方法时,会执行到invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MapperBean mapperBean = myConfiguration.readMapper(this.mapperFile);
//判断是否是xml文件对应的接口
if (!method.getDeclaringClass().getName().equals(mapperBean.getInterfaceName()))
{
//通过method拿到执行的方法所在的接口的名称,与MapperBean存放的接口名比较
return null;
}
//取出MapperBean的functions
List<Function> functions = mapperBean.getFunctions();
//判断当前mapperBean解析对应的XML文件后,有方法
if (null != functions && 0 != functions.size()) {
for (Function function : functions) {
//如果当前要执行的方法和function.getFuncName()一样
//说明我们可以从当前遍历的function对象中,取出相应的信息sql,并执行方法
if (method.getName().equals(function.getFuncName())) {
//如果当前function要执行的SqlType是select,就去执行selectOne
/*
* 说明:
* 1.如果要执行的方法是select,就对应执行selectOne
* 因为我们在MySqlSession只写了一个方法(selectOne)
* 2.实际上原生的MySqlSession中应该有很多的方法,只是这里简化了,
* 实际上应该根据不同的匹配情况调用不同的方法,并且还需要进行参数解析处理,
* 还有比较复杂的字符串处理,拼接sql,处理返回类型等工作
* 3.因为这里主要想实现mybatis生成mapper动态代理对象,调用方法的机制,所以简化
*/
if ("select".equalsIgnoreCase(function.getSqlType())) {
return mySqlSession
.selectOne(function.getSql(), String.valueOf(args[0]));
}
}
}
}
return null;
}
}
(2)修改MySqlSession.java,添加方法,返回动态代理对象
/**
* 1.回 mapper的动态代理对象
* 2.这里的 clazz到时传入的类似 MonsterMapper.class
* 3.返回的就是 MonsterMapper 接口的代理对象
* 4.当执行接口方法时(通过代理对象调用),
* 根据动态代理机制会执行到MyMapperProxy的invoke()方法
* @param clazz
* @param <T>
* @return
*/
public <T> T getMapper(Class<T> clazz) {
//返回动态代理对象
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz},
new MyMapperProxy(this, myConfiguration, clazz));
}
(3)创建 MySessionFactory.java
package com.li.limybatis.sqlsession;
/**
* @author 李
* @version 1.0
* MySessionFactory-会话工厂-返回会话SqlSession
*/
public class MySessionFactory {
public static MySqlSession openSession() {
return new MySqlSession();
}
}
(4)测试
@Test
public void openSession() {
MySqlSession mySqlSession = MySessionFactory.openSession();
MonsterMapper mapper = mySqlSession.getMapper(MonsterMapper.class);
System.out.println("mapper的运行类型=" + mapper.getClass());
Monster monster = mapper.getMonsterById(1);
System.out.println("monster--" + monster);
}
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析: 在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1: print(k)k=k/2A.1000 B.10C.11D.9解析: 按照题意每次循环K/2,直到K值小于等
通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复
在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定
是否有self验证的问题列表。看着那个,我可以确定我知道。我应该复习一下。在学习的过程中,我列了一个这样的list,但它只包含我在某处听说过的项目。我需要一段时间才能找到新的东西。 最佳答案 以下是针对ruby和Rails的一些测试列表。证书名称:RubyonRails谁提供:oDeskIncorporation认证费用:免费网站:https://www.odesk.com/tests/985?pos=0证书名称:RubyonRails提供者:Techgig.com(TimesBusinessSolutionsLimited(T