mybatis入门(三)增删改查

news/2024/5/19 1:38:19 标签: mybatis, sql, jdbc, xml

Mapper XML文件

MyBatis的真正威力在Mapped Statements中。这是魔术发生的地方。对于他们的所有权力,Mapper XML文件相对简单。当然,如果您要将它们与等效的JDBC代码进行比较,您会立即看到95%的代码节省。MyBatis的建立是为了专注于SQL,并竭尽全力保持自己的方式。

Mapper XML文件只有一些第一类元素(按照它们应该定义的顺序):

  • 缓存 - 配置给定名称空间的缓存。
  • cache-ref - 引用另一个命名空间的缓存配置。
  • resultMap - 描述如何从数据库结果集加载对象的最复杂和最强大的元素。
  • 参数 映射 - 弃用!老派的方式来映射参数。内联参数是首选,这个元素将来可能会被删除。这里没有记录。
  • sql - 可以被其他语句引用的可重用的SQL块。
  • 插入 - 映射的INSERT语句。
  • 更新 - 映射的UPDATE语句。
  • 删除 - 映射的DELETE语句。
  • 选择 - 一个映射的SELECT语句。

接下来的部分将详细描述这些元素,从语句本身开始。

选择

select语句是MyBatis中最受欢迎的元素之一。把数据放到数据库中是不可贵的,除非你把它们还原出来,所以大多数应用程序的查询要比修改数据要多得多。对于每一个插入,更新或删除,可能有很多选择。这是MyBatis的创始原则之一,也是查询和结果映射的焦点和努力的原因。select元素对于简单的情况非常简单。例如:

<select id="selectPerson" parameterType="int" resultType="hashmap">
  SELECT * FROM PERSON WHERE ID = #{id}
</select>

这个语句被称为selectPerson,它接受一个int(或Integer)类型的参数,并返回一个由列名映射到行值的HashMap。

注意参数符号:

#{id}

这告诉MyBatis创建一个PreparedStatement参数。使用JDBC,这样的参数将被标识为“?” 在SQL中传递给一个新的PreparedStatement,如下所示:

// Similar JDBC code, NOT MyBatis…
String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);

当然,JDBC需要更多的代码来提取结果并将它们映射到一个对象的实例,这是MyBatis不需要做的事情。关于参数和结果映射的知识还有很多。这些细节保证他们自己的部分,这在本节后面。

select元素具有更多的属性,允许您配置每个语句应该如何表现的细节。

<select
  id="selectPerson"
  parameterType="int"
  parameterMap="deprecated"
  resultType="hashmap"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10000"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">


选择属性
属性 描述
id 此名称空间中的唯一标识符,可用于引用此语句。
parameterType 将传递给此语句的参数的完全限定类名称或别名。这个属性是可选的,因为MyBatis可以计算TypeHandler来使用传递给语句的实际参数。默认值未设置
parameterMap的 这是引用外部参数映射的不推荐的方法使用内联参数映射和parameterType属性。
resultType 将从此语句返回的预期类型的​​完全限定类名或别名。请注意,对于集合,这应该是集合包含的类型,而不是集合本身的类型。使用resultTyperesultMap,不能同时使用。
resultMap 对外部resultMap的命名引用结果图是MyBatis最强大的功能,通过对它们的了解,可以解决很多困难的映射案例。使用resultMapresultType,而不是两者。
flushCache 如果将此语句设置为true,则会在调用此语句时刷新本地和第二级高速缓存。默认值:false选择语句。
useCache 将其设置为true将导致此语句的结果缓存在二级缓存中。默认值: 对于select语句是true
timeout 这会设置驱动程序在抛出异常之前等待数据库返回请求的秒数。默认值是未设置的(取决于驱动程序)。
fetchSize 这是一个驱动程序提示,它将尝试使驱动程序返回大小等于此设置的成批行编号的结果。默认值是未设置的(取决于驱动程序)。
statementType 任何一个STATEMENTPREPAREDCALLABLE这导致MyBatis分别使用Statement, PreparedStatementCallableStatement默认值:PREPARED
resultSetType 任何一个FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE默认值是未设置的(取决于驱动程序)。
databaseId 如果存在已配置的databaseIdProvider,则MyBatis将加载所有没有databaseId 属性的语句或与当前匹配的databaseId如果遇到相同的语句,如果发现有和没有databaseId后者将被丢弃。
resultOrdered 这只适用于嵌套的结果选择语句:如果这是真的,则假定嵌套结果被包含或组合在一起,使得当返回新的主结果行时,不再引用先前的结果行。这使得嵌套结果可以被更多的内存填充。默认: false
resultSets 这只适用于多个结果集。它列出了将由语句返回的结果集并给出每个结果集的名称。名称用逗号分隔。

插入,更新和删除

<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

<update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

数据修改语句插入,更新和删除在它们的实现中非常相似:

   
插入,更新和删除属性
属性描述
id此名称空间中的唯一标识符,可用于引用此语句。
parameterType将传递给此语句的参数的完全限定类名称或别名。这个属性是可选的,因为MyBatis可以计算TypeHandler来使用传递给语句的实际参数。默认值未设置
parameterMap这是引用外部参数映射的不推荐的方法。使用内联参数映射和parameterType属性。
flushCache如果将此语句设置为true,则会在调用此语句时导致第二级和本地缓存刷新。缺省:对于插入,更新和删除语句为true
timeout这会在抛出异常之前设置驱动程序等待数据库从请求返回的最大秒数。默认值是未设置的(取决于驱动程序)。
statementType任何一个STATEMENTPREPAREDCALLABLE这导致MyBatis分别使用Statement, PreparedStatementCallableStatement默认值:PREPARED
useGeneratedKeys(仅插入和更新)这告诉MyBatis使用JDBC getGeneratedKeys方法来检索数据库内部生成的密钥(例如在RDBMS中自动增加字段,如MySQL或SQL Server)。默认:false
keyProperty(仅插入和更新)标识MyBatis将设置由getGeneratedKeysinsert语句selectKey子元素返回的键值的属性默认:未设置如果需要多个生成的列,可以是逗号分隔的属性名称列表。
keyColumn(仅插入和更新)使用生成的密钥设置表中列的名称。这只在某些数据库(如PostgreSQL)中当键列不是表中的第一列时才是必需的。如果需要多个生成的列,可以是逗号分隔的列名称列表。
databaseId如果存在已配置的databaseIdProvider,则MyBatis将加载所有没有databaseId 属性的语句或与当前匹配的databaseId如果遇到相同的语句,如果发现有和没有databaseId后者将被丢弃。

以下是插入,更新和删除语句的一些示例。

<insert id="insertAuthor">
  insert into Author (id,username,password,email,bio)
  values (#{id},#{username},#{password},#{email},#{bio})
</insert>

<update id="updateAuthor">
  update Author set
    username = #{username},
    password = #{password},
    email = #{email},
    bio = #{bio}
  where id = #{id}
</update>

<delete id="deleteAuthor">
  delete from Author where id = #{id}
</delete>

如前所述,插入是一个更丰富的一点,它有一些额外的属性和子元素,使其能够以多种方式处理密钥生成。

首先,如果您的数据库支持自动生成的关键字段(例如MySQL和SQL Server),那么您可以简单地设置useGeneratedKeys =“true”并将keyProperty设置为目标属性,即可完成。例如,如果上面Author表为ID使用了一个自动生成的列类型,那么语句将被修改如下:

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>

如果您的数据库也支持多行插入,则可以传递一个或多个Author数组并检索自动生成的密钥。

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>

MyBatis有另一种方法来处理不支持自动生成列类型的数据库的密钥生成,或者还不支持JDBC驱动程序对自动生成密钥的支持。

这是一个简单的(愚蠢的)例子,它会产生一个随机的ID(你可能永远不会这么做,但是这表明了灵活性以及MyBatis真的不介意):

<insert id="insertAuthor">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
  </selectKey>
  insert into Author
    (id, username, password, email,bio, favourite_section)
  values
    (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>

在上面的例子中,selectKey语句会先运行,Author id属性被设置,然后insert语句被调用。这给你一个类似于你的数据库中自动生成的键的行为,而不会使你的Java代码复杂化。

selectKey元素描述如下:

<selectKey
  keyProperty="id"
  resultType="int"
  order="BEFORE"
  statementType="PREPARED">

   
selectKey属性
属性             描述
keyPropertyselectKey语句的结果应该被设置的目标属性如果需要多个生成的列,可以是逗号分隔的属性名称列表。
keyColumn返回结果集中与该属性匹配的列名称。如果需要多个生成的列,可以是逗号分隔的列名称列表。
resultType结果的类型。MyBatis通常可以解决这个问题,但添加它确实没有什么坏处。MyBatis允许使用任何简单的类型作为键,包括字符串。如果您希望生成多个列,那么可以使用包含期望属性的对象或Map。
order这可以设置为BEFOREAFTER如果设置为BEFORE,那么将首先选择键,设置keyProperty然后执行插入语句。如果设置为AFTER,它将运行insert语句,然后运行selectKey语句 - 对于像Oracle这样的可能在嵌入语句中嵌入序列调用的数据库是很常见的。
statementType和上面一样,MyBatis支持分别映射到StatementPreparedStatementCallableStatement的STATEMENTPREPAREDCALLABLE语句类型。 

sql" style="color:rgb(0,136,204)">SQL

这个元素可以用来定义可以包含在其他语句中的可重用的SQL代码片段。它可以静态地(在加载阶段)参数化。包含实例中的不同属性值可能有所不同。例如:

<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>

然后可以将SQL片段包含在另一个语句中,例如:

<select id="selectUsers" resultType="map">
  select
    <include refid="userColumns"><property name="alias" value="t1"/></include>,
    <include refid="userColumns"><property name="alias" value="t2"/></include>
  from some_table t1
    cross join some_table t2
</select>

属性值也可以用在include子句中,包括refid属性或属性值,例如:

<sql id="sometable">
  ${prefix}Table
</sql>

<sql id="someinclude">
  from
    <include refid="${include_target}"/>
</sql>

<select id="select" resultType="map">
  select
    field1, field2, field3
  <include refid="someinclude">
    <property name="prefix" value="Some"/>
    <property name="include_target" value="sometable"/>
  </include>
</select>

Parameters

在所有的过去的陈述中,你已经看到了简单参数的例子。参数是MyBatis中非常强大的元素。对于简单的情况,大概有90%的情况,对他们来说并不多,例如:


上面的例子演示了一个非常简单的命名参数映射。参数类型被设置为 int,因此参数可以被命名为任何东西。原始数据类型或简单数据类型(如 IntegerString)没有相关属性,因此将完全替换参数的完整值。但是,如果你传入一个复杂的对象,那么行为就有点不同了。例如:

<insert id="insertUser" parameterType="User">
  insert into users (id, username, password)
  values (#{id}, #{username}, #{password})
</insert>

如果User类型的参数对象被传递到该语句中,则会查找id,username和password属性,并将其值传递给PreparedStatement参数。

将参数传递给语句非常简单。但是参数图有很多其他的特点。

首先,像MyBatis的其他部分一样,参数可以指定更具体的数据类型。

#{property,javaType=int,jdbcType=NUMERIC}

像MyBatis的其余部分一样,javaType几乎总是可以从参数对象中确定,除非该对象是一个HashMap然后java类型应规定以确保正确的 类型处理器使用。

:如果null作为值传递,则JDBC类型对于所有可为空的列是JDBC所必需的您可以通过阅读PreparedStatement.setNull()方法的JavaDocs来调查

要进一步自定义类型处理,还可以指定一个特定的TypeHandler 类(或别名),例如:

#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}

所以已经看起来很冗长了,但事实是,你很少会设置其中的任何一个。

对于数字类型,还有一个numericScale用于确定相关的小数位数。

#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}

最后,mode属性允许你指定INOUTINOUT参数。如果参数是 OUTINOUT,那么参数对象属性的实际值将会改变,就像您在调用输出参数时所预期的一样。如果mode = OUT(或INOUT)和 jdbcType = CURSOR(即Oracle REFCURSOR),则必须指定resultMap以将ResultSet 映射参数的类型。请注意,javaType属性在这里是可选的,它将被自动设置为ResultSet如果留空,CURSOR作为jdbcType

#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}

MyBatis也支持更高级的数据类型,比如结构体,但是在注册out参数的时候,你必须告诉这个语句类型的名字。例如(再次,在实践中不要像这样断线):

#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}

尽管所有这些强大的选项,大部分时间你只需指定属性名称,MyBatis将找出其余的。至多,你会指定可空列jdbcType

#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}

字符串替换

默认情况下,使用#{}语法将导致MyBatis生成PreparedStatement属性,并根据PreparedStatement参数(例如?)安全地设置值虽然这是更安全,更快,几乎总是首选,但有时您只是想直接在SQL语句中插入一个未修改的字符串。例如,对于ORDER BY,你可以使用这样的东西:

ORDER BY ${columnName}

这里MyBatis不会修改或转义字符串。

注意接受来自用户的输入并将其提供给未经修改的语句是不安全的。这会导致潜在的SQL注入攻击,因此您应该在这些字段中禁止用户输入,或者始终执行您自己的转义和检查。


http://www.niftyadmin.cn/n/798094.html

相关文章

mybats入门(四)resultMap

ResultMap 在resultMap的元素是MyBatis中最重要最强大的元素。这就是您可以使用JDBC从ResultSet中检索数据的90&#xff05;的代码&#xff0c;在某些情况下允许您执行JDBC甚至不支持的操作。事实上&#xff0c;编写复杂语句的连接映射等效代码可能会跨越数千行代码。ResultMap…

mybatis高级用法(五)resultMap

1.首先&#xff0c;我们先看看一个常见的博客页面的组成&#xff0c;如下&#xff1a; a.页面上能够展示的部分&#xff1a;正文&#xff0c;标题&#xff0c;日期&#xff0c;作者&#xff0c;评论正文&#xff0c;评论时间&#xff0c;评论人等等 b.页面之外的部分&#xff1…

mybatis高级用法resultMap下(六)

上文&#xff0c;我们说到了“has-many”这个问题&#xff0c;在Mybatis中提供给我们另外一个非常有用的元素&#xff1a; 1.<collection>集合 下面给出一个典型的<collection>元素的示例&#xff0c;如下&#xff1a; [html] view plaincopy <collection prope…

mybatis转义

第一种方法&#xff1a; 用转义字符把">"和"<"替换掉&#xff0c;就没有问题了。 <if test"startTime ! null ">AND order_date > #{startTime,jdbcTypeDATE} </if> <if test"endTime ! null ">AND order…

后台对象转换成json返回前台

一、数据封装 1. List集合转换成json代码   List list new ArrayList();   list.add( "first" );   list.add( "second" );   JSONArray jsonArray2 JSONArray.fromObject( list ); 2. Map集合转换成json代码   Map map new HashMap();   m…

JavaScript中的json对象和JAVA中的对象之间转换

Json格式&#xff08;Json字符串&#xff09; &#xff1a; var json{"name": "lily","age":"15"} 对象格式&#xff1a; var map{name: "lily", age:"15"}对象取值&#xff1a; var namemap["name"]; …

mysql中ON DUPLICATE KEY UPDATE 和ignore,REPLACE 之间的区别

一、使用ON DUPLICATE KEY UPDATE 用主键primary或者唯一索引unique区分了唯一性,避免重复插入记录可以使用 insert into table(,,) values(...) ON DUPLICATE KEY UPDATE 更新的内容 insert into sms_template(sms_type,template_content,company_id)VALUES(#{smsType},#{…

小程序项目学习笔记

一、开始&#xff1a; 1、移动设备的分辨率px和rpx&#xff1a; rpx一般是自适应长度&#xff0c;可以根据机子的屏幕大小的不痛来进行自适应&#xff0c;从而使不同屏幕的显示效果相同。 二、如何开始一个项目&#xff1a; &#xff08;由于小程序还在进行快速更迭中&#xff…