目录
4.动态查询(if,trim,where,set,foreach的使用)
这里手动进行添加,通过在已有的spring项目中的pom.xml文件中引入以下依赖
<!-- 添加 MyBatis 框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- 添加 MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
在application.properties中配置以下内容
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/blog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
#配置mybatis的xml文件路径
mybatis.mapper-locations=classpath:mapper/**Mapper.xml
这里关于xml文件路径配置的匹配规则是在当前mapper下所有文件名以Mapper.xml结尾的文件。
如下所示:


其中mapper中需要配置的内容有如下:
<?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="org.example.mapper.UserMapper">
</mapper>
mapper里面就是对于CRUD操作的一些语句,只不过这些语句头需要遵守一些约束和规定,之后才能转化为java对象,并作为返回值返回给java中调用的方法。
查询前的配置:



将查询到的结果集会自动装配到配置的resultMap中

mapper里面的指定方法被调用后会通过之前配置的xml和对应的路径会执行xml文件中的方法
定义service层,然后在该层调用mapper中的方法
通过postman来通过url来访问该资源下的路径
上面就是使用mybatis来对数据库操作的整个流程,接下来就是一些有关xml中关于CRUD语句的具体操作和配置。

seGeneratedKeys: MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键,默认值:false。
keyColumn:设置生成键值在数据库表中的列名;如果生成列不止一个,可以用逗号分隔多个属性名称。
keyProperty:指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。
controller层

service层

mapper层

通过接口插入成功的显示

UserMapper.xml中的sql代码:
<insert id="insertOne" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert
into
user(username, password, nickname)
values (#{username},#{password},#{nickname})
</insert>
基于xml文件配置好的前提下,然后在xml文件中写sql操作

通过构造前端接口,来调用mybatis中的sql来进行验证,执行顺序如下:




对于查询操作来说,需要在xml中配置结果集映射,因为需要将查找中的数据映射为一个java对象。
首先在xml文件中使用resultMap,然后设置id,之后的查询语句需要根据该id来进行转化为type中的对象,其中type中为model类的位置(类路径),然后里面就是关于映射关系的指定,其中id是数据库中关于主键的映射,如果不是主键,就使用result,对于属性中的参数,如column是数据库中的字段名,而property是类的成员变量。
<!-- 这里是配置有关查询到的结果集转化为哪一个-->
<!-- column代表数据库中的字段-->
<resultMap id="ResultBaseMap" type="org.example.model.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="nickname" property="nickname"></result>
<result column="github" property="github"></result>
<result column="head" property="head"></result>
</resultMap>

#{}是预编译占位符,在处理是,会将该位置的数据先转化为?,然后在执行PreparedStament中的set方法时,将?替换变量值。如果是字符串,会添加""。
${}是直接进行替换为变量的值,存在sql注入问题。
假如传递的数据是sort ,对于#{},最终会处理成"sort",而${}就是sort。
在使用like的时候,一般是模糊查询,在mybatis中需要使用concat函数来将%与#{变量值}来进行拼接。
concat(str1, str2, str3...)是将str1和str2和str3等全部进行拼接起来。
<!-- like查询-->
<select id="selectLike" resultMap="ResultBaseMap">
select
id,
username,
password
from
user
where password like concat('%',#{password},'%');
</select>
对于多表查询时,都需要使用resultMap来进行配置,在配置前还需要给对象中添加新的属性。例如一个用户登录表和用户信息表之间的关系是一对一,在进行关联查询的时候首先需要给User类中添加一个Message类型的成员变量,然后再在resultMap中除了配置有关User信息的属性外,还需要添加一个<association property="" resultMap="" columnPrefix="">属性.
property是在User中新添加的成员message, resultMap是需要关联的结果集的映射,而columnPrefix是对于查询的结果字段添加前缀,如果两个表中右重复字段,可以通过该字段进行区分,之后在associate中配置的resultMap中会去除掉前缀进行匹配。
<!-- 一对一关联自己的message信息-->
<resultMap id="ResultBaseMap2" type="org.example.model.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="nickname" property="nickname"></result>
<result column="github" property="github"></result>
<result column="head" property="head"></result>
<association property="message" resultMap="org.example.mapper.UMMapper.BaseResultMap"
columnPrefix="m_"></association>
</resultMap>
<!-- 一对一关联查询-->
<select id="onebyone" resultMap="ResultBaseMap2">
select
u.id,
u.username,
m.id_card m_id_card,
m.id m_id,
m.user_id m_user_id
from user u left join message m on u.id=m.user_id;
</select>
查询和配置关系
对于一个用户表和文章表的关系是一对多,一个用户可以有多篇文章,Mybatis中也是通过resultMap来对查询结果集进行配置,然后再对查询结果中映射的对象中添加一个新的集合属性(因为是一对多关系),和一对一不同的是resultMap中设置的是collection属性,其他的配置规则基本不变。
<!-- 这里是配置有关查询到的结果集转化为哪一个-->
<!-- column代表数据库中的字段-->
<resultMap id="ResultBaseMap" type="org.example.model.User">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="nickname" property="nickname"></result>
<result column="github" property="github"></result>
<result column="head" property="head"></result>
<collection property="articles" resultMap="org.example.mapper.ArticleMapper.ResultBaseMap"
columnPrefix="a_"></collection>
</resultMap>
<!--关联查询,一个用户对应多篇文章-->
<select id="selectUserAndArticle" resultMap="ResultBaseMap">
select
u.id,
u.username,
u.password,
u.nickname,
u.github,
u.head,
a.id a_id,
a.title a_title,
a.date a_date,
a.content a_content
from user u join article a on u.id=a.user_id
</select>

标签为:<if test="属性值不为空"> </if>
如果对于一个参数是否传递是不确定的(可能为空或不为空),我们可以使用if来进行判断,如果传了就在sql中显示,没有传就不显示。
如注册用户时,有些信息可以不用传递,如头像等,这时候就可以在mybatis中使用if来进行过滤该参数。

<insert id="insertSelective">
insert into user(
username,
nickname,
password
<if test="head!=null"> ,head </if>
<if test="github!=null"> ,github </if>
)
values (
#{username},
#{nickname},
#{password}
<if test="head!=null"> ,#{head} </if>
<if test="github!=null"> ,#{github} </if>
)
</insert>
首先trim标签中有多个参数,分别为:
prefix=“” 表示整个语句块以prefix中的内容作为前缀
suffix=“” 表示整个语句块以suffix中的内容作为后缀
prefixOverrides=“” 表示整个语句块要去掉的前缀
suffixOverrides=“” 表示整个语句块要去掉的后缀
以之前的选择插入语句为例,来使用上面的参数:
<insert id="insertParam">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username!=null">
username,
</if>
<if test="nickname!=null">
nickname,
</if>
<if test="password!=null">
password,
</if>
<if test="github!=null">github</if>
</trim>
<trim prefix="values(" suffix=")" suffixOverrides=",">
<if test="username!=null">
#{username},
</if>
<if test="nickname">
#{nickname},
</if>
<if test="password!=null">
#{password},
</if>
<if test="github!=null">
#{github},
</if>
</trim>
</insert>
<where></where>是用在条件查询中(也可以使用上面的trim),对于where中的<if></if>里面的内容,写成and 属性名=属性值,之后会自动去掉第一个and。
如下所示,如果传递的password和username不为空,就根据这两个条件进行过滤:
<select id="selectByWhere" resultMap="BaseResultMap">
select * from user
<where>
<if test="password!=null">
and password=#{password}
</if>
<if test="username!=null">
and username=#{username}
</if>
</where>
</select>
用于sql修改中,会自动去除掉set中的if属性中的.
<update id="updateSet">
update user
<set>
<if test="username!=null">
username=#{username},
</if>
<if test="nickname!=null">
nickname=#{nickname},
</if>
<if test="password!=null">
password=#{password},
</if>
</set>
where id=#{id}
</update>
可以对于传入的集合进行遍历,里面的参数如下所示:
collection:用于绑定方法参数中的集合
item:遍历时的每一个对象
open:语句块开头的字符串
close:语句块结束的字符串
separator:每次遍历之间的分隔符
示例,根据list中的id号来进行批量删除:
<delete id="deleteByIds">
delete from user where id in <foreach collection="list" open="(" close=")" separator="," item="item">
#{item}
</foreach>
</delete>

我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po