11、多环境切换、注解方式、增删改返回值、事务自动提交、自增、参数、null、HashMap、ResultMap、别名、sql标签、内置参数、模糊查询

1.数据库环境切换(驱动jar)

a、切换environment

//db.properties
#oracle
oracle.driver=oracle.jdbc.OracleDriver
oracle.url=jdbc:oracle:thin:@127.0.0.1:1521:ORCL
oracle.username=root
oracle.password=123456

#mysql
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8
mysql.username=root
mysql.password=123456

注意:db.properties里面要检查空格,如果有多余的空格会报错

//在config.xml中

<properties resource="db.properties" />

<!-- default和id值相同时才能连接成功,测试类中也可以修改默认值 -->
<environments default="devMysql">
	<!-- 开发环境(自己的计算机) -->
	<environment id="devOracle">
		<!-- 事务提交方式: 
		  JDBC:利用JDBC方式处理事务(手工) 
		  MANAGED:将事务交由其他组件去托管(spring,jobss)默认会关闭连接
		 -->
		<transactionManager type="JDBC" />
		<!-- 取消MANAGED的默认关闭连接 -->
		<!-- <property name="closeConnection" value="false" /> -->
		
		<!-- 数据源类型:
		  POOLED:使用数据库连接池(三方)
		  UNPOOLED:传统的JDBC模式,每次访问数据库,均需要打开、关闭等数据库操作,比较消耗性能 
		  JNDI:从tomcat中获取一个内置的数据库连接池
		   -->
		<dataSource type="POOLED">
			<!-- 配置数据库信息 -->
			<property name="driver" value="${oracle.driver}" />
			<property name="url" value="${oracle.url}" />
			<property name="username" value="${oracle.username}" />
			<property name="password" value="${oracle.password}" />
		</dataSource>
	</environment>

	<!-- 真正的项目应该在 发布的那台计算机上运行 -->
	<environment id="devMysql">
		<!-- 数据库事务处理 -->
		<transactionManager type="JDBC" />
		<!-- 配置数据库信息 -->
		<dataSource type="POOLED">
			<property name="driver" value="${mysql.driver}" />
			<property name="url" value="${mysql.url}" />
			<property name="username" value="${mysql.username}" />
			<property name="password" value="${mysql.password}" />
		</dataSource>
	</environment>
</environments>

b、配置Provider别名

<!-- 配置数据库支持类 -->
<databaseIdProvider type="DB_VENDOR">
    <!-- value是别名 -->
	<property name="MySQL" value="mysql"/>
	<property name="Oracle" value="oracle"/>
	<property name="SQL Server" value="sql server"/>
</databaseIdProvider>

c、写不同数据库的SQL语句

d、在xxxMapper.xml中配置databaseId=“mysql”

<select id="queryPersonByIdWithConverter" resultMap="personResult" parameterType="int" databaseId="oracle">
	select * from Person where id = #{id}
</select>
<select id="queryPersonByIdWithConverter" resultMap="personResult" parameterType="int" databaseId="mysql">
	select * from Person where id = #{id}
</select>

如果xxxMapper.xml的sql标签仅有一个不带databaseId的标签,则该标签会自动适应当前数据库
如果既有不带,又有带databaseId标签的sql,则程序会优先使用带databaseId的标签

2.注解方式(小项目)

推荐使用xml

a、将SQL语句写在接口的方法上面的注解

//xxxMapper.java
//操作mybatis的接口
public interface PersonMapper {
	/* 1、方法名和mapper.xml文件中标签的id相同
	 * 2、方法的输入参数和mapper.xml文件中标签的parameterType一致
	 * 3、方法的返回值和mapper.xml文件中标签的resultType一致
	 * 4、接口里的方法默认public abstract,所以可以省略 
	 */
	@Select("select * from person ")
	List<Person> queryPersonByIdWithOneToOneAndLazyLoad();
}

b、将接口的全类名写入< mapper>,让mybatis知道sql语句此时是储存在接口中

<mappers>
	<!-- 加载映射文件 -->
	<mapper class="org.lanqiao.mapper.PersonMapper"/>
	<!-- <mapper resource="org/lanqiao/mapper/personMapper.xml" /> -->
</mappers>

注解/xml都支持批量引入

<mappers>
	<!-- 加载映射文件 -->
	<!-- 可以将org.lanqiao.mapper包中所有的注解接口和xml全部一次性引入 -->
	<package name="org.lanqiao.mapper"/>
	<!-- <mapper class="org.lanqiao.mapper.PersonMapper"/> -->
	<!-- <mapper resource="org/lanqiao/mapper/personMapper.xml" /> -->
</mappers>

3.增删改的返回值(不包括查)

返回值可以使void、Integer、Boolean…
操作:只需要在接口中修改,不需要在xml文件中操作

4.事务自动提交

手动提交(推荐):

SqlSession session = sessionFactory.openSession();
//手动提交
session.commit();

自动提交(增删改):

SqlSession session = sessionFactory.openSession(true);

5.自增

MySQL支持自增,Oracle不支持自增

对于支持自增的MySQL,只需要在插入语句中加入useGeneratedKeys="true" keyProperty="id"

keyProperty值为数据库中的自增字段名

//xxxMapper.xml
<insert id="addPersonWithConverter" parameterType="Person" useGeneratedKeys="true" keyProperty="id">
    insert into person(id,name,age,sex) values(#{id},#{name},#{age},#{sex,javaType=boolean,jdbcType=INTEGER})
</insert>
//测试类方法
public static void addPersonWithConverter(Person person) throws IOException {
	//加载Mybatis配置文件(为了访问数据库)
	Reader reader = Resources.getResourceAsReader("config.xml");
	//可以在build中修改config.xml中developments的默认值
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader,"devMysql");
	//session - connection
	SqlSession session = sessionFactory.openSession();
	PersonMapper personMapper=session.getMapper(PersonMapper.class);
	//接口中的方法--》SQL语句
	personMapper.addPersonWithConverter(person);
	System.err.println(person.getId());
	//提交事务,不然数据进不去数据库中  
	session.commit();
	session.close();
}
public static void main(String[] args) throws IOException {
	addPersonWithConverter(new Person(null,"cxx",11,true));
}

如果不修改SQL语句,则输出null,修改后输出数据库中对应的id值

对于Oracle不支持自增:通过序列模拟实现

create sequence seq increment by 1 start with 1;
序列的两个属性:
nextval:序列中下一个值
currval:当前值
insert into person values(seq.nextval,"cxx",11,true);

//xxxMapper.xml
//方式一:
<insert id="addPersonWithConverter" parameterType="Person">
    <selectKey keyProperty="id" resultType="Integer" order="BEFORE">
        select seq.nextval from dual
    </selectKey>
    insert into person(id,name,age,sex) values(#{id},#{name},#{age},#{sex,javaType=boolean,jdbcType=INTEGER})
</insert>
//方式二:
<insert id="addPersonWithConverter" parameterType="Person">
    <selectKey keyProperty="id" resultType="Integer" order="AFTER">
        select seq.currval from dual
    </selectKey>
    insert into person(id,name,age,sex) values(seq.nextval,#{name},#{age},#{sex,javaType=boolean,jdbcType=INTEGER})
</insert>

6.参数

目前将多个参数封装到一个JavaBean对象(pojo),然后使用该对象传递

传入多个参数时,不用在xxxMapper.xml中编写parameterType。
//xxxMapper.xml
<!-- 
<insert id="addPersonWithConverter" parameterType="Person" useGeneratedKeys="true" keyProperty="id">
    insert into person(id,name,age,sex) values(#{id},#{name},#{age},#{sex,javaType=boolean,jdbcType=INTEGER})
</insert>
 -->
<insert id="addPersonWithConverter" useGeneratedKeys="true" keyProperty="id">
    insert into person(id,name,age,sex) values(#{id},#{name},#{age},#{sex,javaType=boolean,jdbcType=INTEGER})
</insert>
//xxxMapper.java
import org.apache.ibatis.annotations.Param;
import org.lanqiao.entity.Person;
//操作mybatis的接口
public interface PersonMapper {
	/* 1、方法名和mapper.xml文件中标签的id相同
	 * 2、方法的输入参数和mapper.xml文件中标签的parameterType一致
	 * 3、方法的返回值和mapper.xml文件中标签的resultType一致
	 * 4、接口里的方法默认public abstract,所以可以省略 
	 */
	void addPersonWithConverter(Person person);
	void addPersonWithConverter(@Param("id")Integer id,@Param("name")String name,@Param("age")int age,@Param("sex")boolean sex);
}
//测试类方法
public static void addPersonWithConverter(Integer id,String name,int age,boolean sex) throws IOException {
	//加载Mybatis配置文件(为了访问数据库)
	Reader reader = Resources.getResourceAsReader("config.xml");
	//可以在build中修改config.xml中developments的默认值
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader,"devMysql");
	//session - connection
	SqlSession session = sessionFactory.openSession();
	PersonMapper personMapper=session.getMapper(PersonMapper.class);
	//接口中的方法--》SQL语句
	personMapper.addPersonWithConverter(id,name,age,sex);
	System.err.println(id);
	//提交事务,不然数据进不去数据库中  
	session.commit();
	session.close();
}
public static void main(String[] args) throws IOException {
	addPersonWithConverter(null,"cxx",11,true);
}
参数中既有简单类型也有对象类型
//xxxMapper.java
import org.apache.ibatis.annotations.Param;
import org.lanqiao.entity.Person;
//操作mybatis的接口
public interface PersonMapper {
	/* 1、方法名和mapper.xml文件中标签的id相同
	 * 2、方法的输入参数和mapper.xml文件中标签的parameterType一致
	 * 3、方法的返回值和mapper.xml文件中标签的resultType一致
	 * 4、接口里的方法默认public abstract,所以可以省略 
	 */
	void addPersonWithConverter(Person person);
	void addPersonWithConverter(@Param("id")Integer id,@Param("name")String name,@Param("age")int age,@Param("sex")boolean sex);
	void addPersonWithConverter(@Param("id")Integer id,@Param("per")Person person);
}
//xxxMapper.xml
<!-- 
<insert id="addPersonWithConverter" parameterType="Person" useGeneratedKeys="true" keyProperty="id">
    insert into person(id,name,age,sex) values(#{id},#{name},#{age},#{sex,javaType=boolean,jdbcType=INTEGER})
</insert>
<insert id="addPersonWithConverter" useGeneratedKeys="true" keyProperty="id">
    insert into person(id,name,age,sex) values(#{id},#{name},#{age},#{sex,javaType=boolean,jdbcType=INTEGER})
</insert>
 -->
<insert id="addPersonWithConverter" useGeneratedKeys="true" keyProperty="id">
    insert into person(id,name,age,sex) values(#{id},#{per.name},#{per.age},#{per.sex,javaType=boolean,jdbcType=INTEGER})
</insert>

7.增加null

Oracle:如果插入的字段是Null,提示错误:Other而不是null
MySQL:如果插入的字段是Null(没有约束),可以正常执行

原因:各个数据库在MyBatis中对各种数据类型的默认值不一致。MyBatis中,jdbcTypeForNull(如果是Null),则默认值为Other。对于Other,MySQL能够处理(NULL),但是Oracle不行

解决:Oracle:null --> OTHER,需要手工告诉Oracle:other --> null

a、当某个数据类型Oracle无法处理时,告诉它用默认值null;注意,此时设置的jdbcType=NULL不会影响正常的赋值
<insert id="addPerson" databaseId="oracle">
    insert into person(id,name) values(#{id},#{name,jdbcType=NULL})
</insert>
b、配置MyBatis全局配置文件config.xml(推荐)
<settings>
   <setting name="jdbcTypeForNull" value="NULL"/>
</settings>

8.返回值为HashMap

<!-- resultType为HashMap  -->
<!-- 别名作为map的key -->	
<!-- 动态SQL -->
<!-- 在where后面加1=1或者使用<where>标签解决and问题,<where>标签会自动处理第一个and -->
<select id="queryAllPersonByNameOrAgeWithSQLTag" parameterType="Person" resultType="HashMap" >
	select id "perid",name "pername" from Person
	<where>
	    <if test="name!=null and name!='' ">
		    and name=#{name}
		</if>
		<if test="age!=null and age!=0 ">
		    and age=#{age}
		</if>
	</where>
</select>

其中id是数据库的字段名,"perid"是id的别名,用于在map中取值时使用(作为map的key)。map.get(“perid”)

如果不加别名,map的key就是字段名

@MapKey("ID")//oracle的元数据(字段名、表名)都是大写
HashMap<Integer,Person> queryPersonsByHashMap();

<select id="queryPersonByHashMap" resultType="HashMap">
    select id,name,age from person
</select>

程序根据select的返回值知道map的value就是Person,根据@MapKey("ID")知道map的key是id

9.ResultMap

如果数据库的字段名和JavaBean的属性名不一致时,可以使用ResultMap进行对应。

在ResultMap中,还可以使用鉴别器:对相同SQL中不同字段值进行判断,从而进行不同的处理。

<!-- 一对一和延迟加载 -->
<select id="queryPersonByIdWithOneToOneAndLazyLoad" parameterType="int" resultMap="Person_PersonCard_lazyLoad" databaseId="mysql">
	select * from person 
</select>

<resultMap type="Person" id="Person_PersonCard_lazyLoad">
    <!-- 分为主键id和非主键result -->
    <id property="id" column="id" />
    <!-- <result property="name" column="name" /> -->
    <!-- 鉴别器:对查询结果进行分支处理:如果是a年级则真名,如果b年级则昵称 -->
    <discriminator javaType="String" column="className">
        <case value="a" resultType="Person">
            <result column="name" property="name" />
        </case>
        <!-- resultType值与此resultMap的type一致 -->
        <case value="b" resultType="Person">
            <result column="nickName" property="name" />
        </case>
    </discriminator>
    <result property="age" column="age" />
    <!-- jdbcType的值要大写 -->
    <result property="sex" column="sex" javaType="boolean" jdbcType="INTEGER" />
    <!-- 一对一时,对象成员使用association映射 -->
    <!-- 采用延迟加载:在查询学生是,并不立即加载学生证信息 -->
    <association property="personCard" javaType="PersonCard" select="org.lanqiao.mapper.PersonCardMapper.queryCardById" column="cardId">
       <!-- <id property="cardId" column="cardId" />
       <result property="cardInfo" column="cardInfo" /> -->
    </association>
</resultMap>

10.别名

//在config.xml中
<!-- 设置单个/多个别名(别名忽略大小写) -->
<typeAliases>
   <!-- 设置单个别名 -->
   <!-- <typeAlias type="org.lanqiao.entity.Person" alias="Person"/> -->
   <!-- 批量设置别名,以下会自动将该包(和子包)中的所有类批量定义别名:别名就是类名 -->
   <package name="org.lanqiao.entity"/>
</typeAliases>

如果在批量设置别名是,出现了冲突。例如org.lanqiao.entity包中有个Person类,而org.lanqiao.entity包的子包org.lanqiao.entity.mybatis包中也有个Person类;则可以使用@Alias(“myPerson”)区分

@Alias("myPerson")
public class Person implements Serializable{
}

11.trim标签

<where>可以处理拼接SQL中开头第一个and
<trim>可以处理拼接SQL中开头或结尾第一个and
<trim prefix="where" prefixOverrides="and"></trim>
prefix="where"给拼接的SQL拼接一个where
prefixOverrides="and"处理拼接SQL中开头,第一个and
suffixOverrides="and"处理拼接SQL中结尾,最后一个and
prefix拼接prefixOverrides删除,如果有则删除

12.内置参数

_parameter:代表mybatis的输入参数
_databaseId:代表当前数据库名字

例如:在下面例子中if标签中test即可以使用name,因为name是parameterType值Person的属性,也可以使用_parameter.name

<!-- resultType为HashMap  -->
<!-- 别名作为map的key -->	
<!-- 动态SQL -->
<!-- 在where后面加1=1或者使用<where>标签解决and问题,<where>标签会自动处理第一个and -->
<select id="queryAllPersonByNameOrAgeWithSQLTag" parameterType="Person" resultType="HashMap" >
	select id "id",name "name" from Person
	<where>
	    <if test="name!=null and name!='' ">
		    and name=#{name}
		</if>
		<if test="age!=null and age!=0 ">
		    and age=#{age}
		</if>
	</where>
</select>

13.模糊查询

a、${}:原样输出
select * from Person where name like '%${name}%'
b、传值时
//测试类中
person.setName("%c%");
//xxxMapper.xml中
select * from Person where name like #{name}
c、bind参数

通过bind将传入的name进行了处理

//在xxxMapper.xml中
<select id="queryPersonByNameOrAgeWithHashMap" parameterType="HashMap" resultType="Person">
    <bind name="_queryName" value="'%'+name+'%'"/>
	select * from Person where name like #{_queryName} or age=#{age}
</select>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值