myBatis笔记

myBatis是一个小巧玲珑的orm框架,使用myBatis前应该先创建数据库和表,然后在写对应的Javabean和映射文件。

使用myBatis前准备:
1.所需的jar包包括:【必须】
mybatis-3.2.0.jar
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
slf4j-api-1.7.2.jar
slf4j-log4j12-1.7.2.jar
mybatis-3.2.0-javadoc.jar
mybatis-3.2.0-sources.jar
mysql-connector-java-5.1.7-bin.jar
2.在官方案例中拷贝一个log4j.properties配置文件到src下,日志文件【必须】
3.在官方案例中拷贝一个Configuration.xml,并修改配置;具体配置【必须】
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
<typeAliases>
<!--
别名:
给类com.mxf.bean.User设置一个别名 ‘User’,以后再使用到 com.mxf.bean.User的时候都可以使用别名
-->
<typeAlias type="com.mxf.bean.User" alias="User"/>
</typeAliases>
<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" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- 配置映射文件 -->
<mapper resource="com/mxf/bean/UserMapper.xml" />
</mappers>
</configuration>

1.HelloWorld第一个程序

1.1 在前期准备工作做完以后,开始写我们的Javabean,和hibernate一样,要与数据库基本对应:
public class User implements Serializable{

private static final long serialVersionUID = 1L;
private int id;
private String userName;
private String userAddress;
private int userAge;
此处省略get、set方法
}

1.2 Javabean对应的数据库表

Create Table

CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(50) default NULL,
`userage` int(11) default NULL,
`useraddress` varchar(200) default NULL,
PRIMARY KEY (`id`)
)

1.3 做好前几步后,我们需要创建UserMapper.xml(Javabean对应的配置文件,该配置文件主要写对数据库的操作(SQL语句))

<?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="com.mxf.mapper.UserMap"><!--如果采用接口编程,命名空间就是接口的全路径 -->
<!--
resultType="User"中的User表示别名,见Configuration.xml中的别名配置
parameterType="int" 参数类型,指sql语句中的参数 id
-->
<select id="selectUserById" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
</mapper>

该配置文件要在Configuration.xml中声明,如果不声明,程序找不到Javabean和Javabean对应的映射文件,就无法操作数据库

1.4 验证配置信息是否正确

1.4.1 创建工具类

package com.mxf.dao;

public class MybatisUtil {

private InputStream in;
private static SqlSessionFactory sqlSessionFactory = null;
private static MybatisUtil instance = null;

private MybatisUtil() {
try {
in = Resources.getResourceAsStream("Configuration.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

public static MybatisUtil getInstance() {
if (null == instance) {
instance = new MybatisUtil();
}
return instance;
}

public SqlSession getSession(){
return sqlSessionFactory.openSession();
}
public void closeSession(SqlSession session){
if(null!=session){
session.close();
}
}
}

因为程序运行需要加载Configuration.xml来获得SqlSessionFactory,才能得到SqlSession来操作数据库,并且SqlSessionFactory是一个重量级的SqlSession
的工厂,所以程序中只保留一个即可,故采用单例模式

1.4.2 myBatis提倡接口编程,这样会非常方便。所以我们来为User对数据库的操作来创建一个接口

因为接口和User的映射文件有某种特殊关系,所以我们为接口取名为UserMap.java(一般情况下我们将UserMapper.xml和UserMap.java放在一个包内进行管理)

接口内的代码:

package com.mxf.mapper;

import com.mxf.bean.User;

public interface UserMap {

/**
* UserMapper.xml文件中的id对应接口中的 方法名;
* parameterType对应接口方法中的参数 id;
* resultType对应接口中的返回值User
* <select id="selectUserById" parameterType="int" resultType="User">
*
* @param id
* @return
*/
public User selectUserById(int id);
}

1.4.3 验证信息:

package com.mxf.test;

/**
* 面向接口编程
* @author mxf
*
*/
public class Test2 {
public static void main(String[] args) throws IOException {
SqlSession session = MybatisUtil.getInstance().getSession();
//获取接口
UserMap map = session.getMapper(UserMap.class);//将接口的字节码给getMapper
//执行接口中的方法,因为接口中的方法和映射文件相对应
User user = map.selectUserById(1);
System.out.println(user.getUserName() + " " + user.getUserAge());
MybatisUtil.getInstance().closeSession(session);
}
}

这样我们就能轻松查询到数据库的指定信息了

1.50 总结

从HelloWorld就可以看出为什么myBatis为什么这么受人们青睐了。
1.小巧
2.程序员任意写SQL来操作数据库
3.相比hibernate工作量相对小一点


2.增删改查

2.1 查找

2.1.1 查询全部信息

<!-- id和映射文件对应的接口的方法名相同 -->
<select id="selectUsers" resultMap="listUsers">
select * from user
</select>

该查找条件下的返回值为集合类型resultMap="listUsers";所以需要在该配置文件内构建一个名为listUsers的集合,如下

<!-- 声明列和属性对应 [column对应数据库表字段,property对应javabean属性]-->
<resultMap type="User" id="listUsers">
<id column="id" property="id" />
<result column="username" property="userName" />
<result column="userage" property="userAge" />
<result column="useraddress" property="userAddress" />
</resultMap>

该查询条件对应的接口中的方法:

public List<User> selectUsers();

测试代码:

UserMap usermap = sqlSession.getMapper(UserMap.class);
List<User> users = map.selectUsers();
for(User user : users){
System.out.println(user.getId()+" "+user.getUserName()+" "+user.getUserAge()+" "+user.getUserAddress());
}

2.1.2 根据给定id查询对应信息

<select id="selectUsers2" resultType="java.util.Map">
select * from user where id=1
</select>

注意:该返回值类型为java.util.Map,意思就是查询出一条数据库记录保存到java.util.Map中

该查询条件对应的接口中的方法:

public Map selectUsers2();

测试代码:

UserMap usermap = sqlSession.getMapper(UserMap.class);
Map map = usermap.selectUsers2();
for(Object key : map.keySet()){
System.out.println(key+" "+map.get(key));
}

2.1.3 根据传入参数查询对应信息

<select id="selectUsers3" resultMap="listUsers" parameterType="String">
select * from user where username like ${username} or id = #{1}
</select>

返回值类型是一个集合listUsers,参数类型为String,如果采用占位符的形式(#{username}或者#{0})来读取接口中传入的username参数,取不到值(原因:该参数与javabean中的属性名称不匹配)
所以采取这种方式来取接口中传入的参数值${username},这样的话,接口中的参数传入形式应该这样写:
public List<User> selectUsers3(@Param("username") String username, int id);
在username前加@Param("username"),这样配置文件中的SQL就能取到传入的参数值

该查询条件对应的接口中的方法:

public List<User> selectUsers3(@Param("username") String username, int id);

测试代码:

List<User> users = usermap.selectUsers3("'%a%'",1);
for(User user : users){
System.out.println(user.getId()+" "+user.getUserName()+" "+user.getUserAge()+" "+user.getUserAddress());
}

不明白?----> 接口中传入的参数有两个类型:String,int ;在写SQL语句时配置的参数类型就一个String,运行没有问题。

2.1.4 根据传入参数查询对应信息并进行排序

<select id="selectUsers4" resultMap="listUsers" parameterType="String">
select * from user where username like ${username} or id = #{1} order by ${orderName} ${orderType}
</select>

不难看出返回值类型是一个集合listUsers,参数类型为String;
该查询语句为条件模糊查询,参数个数为4,分别为:
username:用户名
#{1}:第二个参数
orderName:排序的名称(根据什么排序)
orderType:排序类型(正序或倒序)

该查询条件对应的接口中的方法:

public List<User> selectUsers4(@Param("username") String username, int id,
@Param("orderName") String orderName,
@Param("orderType") String orderType);

测试代码:

List<User> users = usermap.selectUsers4("'%a%'",1,"username","desc");
for(User user : users){
System.out.println(user.getId()+" "+user.getUserName()+" "+user.getUserAge()+" "+user.getUserAddress());
}
2.1.5 根据传入对象进行SQL判断查找

<select id="selectUsers5" resultMap="listUsers" parameterType="User">
select * from user
<if test="userName!=null">
where username like ${userName}
</if>
<if test="orderName!=null and orderType!=null">
order by ${orderName} ${orderType}
</if>
</select>

参数为User,该User只是一个别名,真正对应的类在Configuration.xml中的typeAliases配置中
SQL语句中可以添加判断语句,防止传入参数为null现象,详细见文档

该查询条件对应的接口中的方法:

public List<User> selectUsers5(User user);

测试代码:

User u = new User();
u.setId(1);
u.setUserName("'%a%'");
u.setOrderName("username");
u.setOrderType("desc");
List<User> users = usermap.selectUsers5(u);
for(User user : users){
System.out.println(user.getId()+" "+user.getUserName()+" "+user.getUserAge()+" "+user.getUserAddress());
}
2.1.6 根据传入的集合进行查询

<select id="selectUserByCollection" resultMap="listUsers">
select * from user where id in
<foreach collection="list" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</select>

我相信,这是mybatis最大的优点之一,可以根据传入的集合进行数据库表的查询
返回值类型listUsers集合
在看SQL语句:该SQL中添加了foreach来便利参数(集合);
foreach中的配置信息:
collection="list" 传入的集合名称
item="item" 用来遍历集合的参数,一般不改变,默认item
index="index" 索引,一般不改变,默认index
open="(" 拼接字符串"("
separator="," 拼接字符串","
close=")" 拼接字符串")"

下面来看看原来写定的SQL:
select * from user where id in (1,2,3,4)

和foreach遍历的SQL比较起来很容易就明白了。

该查询条件对应的接口中的方法:

public List<User> selectUserByCollection(List list);

测试代码:

List list = new ArrayList();
list.add(1);
list.add(2);
List<User> users = usermap.selectUserByCollection(list );
for(User user : users){
System.out.println(user.getId()+" "+user.getUserName()+" "+user.getUserAge()+" "+user.getUserAddress());
}

2.2 添加

2.2.1 添加

<insert id="addUser" keyProperty="id" useGeneratedKeys="true"
parameterType="User">
insert into user(username,userage,useraddress)
values(#{userName},#{userAge},#{userAddress})
</insert>

keyProperty="id" 主键声明
useGeneratedKeys="true" 运用主键自增长方式
parameterType="User" 传入参数类型 User

#{userName},#{userAge},#{userAddress}这些参数mybatis会自动到User的属性中查找

该添加语句对应的接口中的方法:

public void addUser(User user);

测试代码:

User user = new User();
user.setUserName("老王");
user.setUserAge(35);
user.setUserAddress("河南郑州");
usermap.addUser(user);

2.3 更新

2.3.1 更新

<update id="updateUser" parameterType="User">
update user
<set>
<if test="userName != null">username=#{userName},</if>
<if test="userAge != null">userage=#{userAge},</if>
<if test="userAddress != null">useraddress=#{userAddress}</if>
</set>
where id=#{id}
</update>

SQL语句中出现了set代码块,改代码块的作用是:
1.帮你把SQL语句补齐 update user set ...
2.判断插入条件是否为空,如果为空,则不更新;不为空,更新
3.如果全部为空 则不更新 update user where id=#{id}

该更新语句对应的接口方法:

public void updateUser(User user);

测试代码:

User user = new User();
user.setId(3);
user.setUserName("小王1");
user.setUserAge(18);
user.setUserAddress("北京海淀");
usermap.updateUser(user);

2.4 删除

2.4.1 删除

<delete id="deleteUserById" parameterType="User">
delete from user where
id=#{id}
</delete>

参数类型User mybatis会到User类中查找值并赋给id

该删除语句对应的接口方法:

public void deleteUserById(User user);

测试代码:

User user = new User();
user.setId(4);
usermap.deleteUserById(user );

3.表之间的关联关系

3.1 一对一

我们选择Person(人)和Idcard(身份证)来完成一对一的关联关系

数据库表:

Create Table

CREATE TABLE `idcard` (
`id` int(11) NOT NULL auto_increment,
`idnum` varchar(20) character set utf8 default NULL,
PRIMARY KEY (`id`)
)


Create Table

CREATE TABLE `person` (
`id` int(11) NOT NULL auto_increment,
`age` int(11) default NULL,
`name` varchar(20) character set utf8 default NULL,
`idcard` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `person_fk` (`idcard`),
CONSTRAINT `person_fk` FOREIGN KEY (`idcard`) REFERENCES `idcard` (`id`)
)

数据表对应的Java实体类:

public class Idcard implements Serializable{

private static final long serialVersionUID = 1L;
private int cid;
private String idnum;
省略get、set方法
}

public class Person implements Serializable{

private static final long serialVersionUID = 1L;
private int pid;
private String name;
private int age;

private Idcard idcard;
省略get、set方法
}

由实体类和数据库表可以看出,表idcard为主表,person为从表

3.1.1 一对一查询 (注意SQL语句的面向对象传入参数)

mybatis中没有级联的概念,所以在表与表关联关系操作的时候是这样实现的:

表A对应的实体类写自己的SQL操作A;
表B对应的实体类写自己的SQL操作B;
它们之间的联系在于外键,外键不能实现级联操作。

PersonMapper.xml内的配置:

****第一种通过person查出所有人包括idcard的办法
<!-- 查询所有人 -->
<select id="selectAll" resultMap="persons">
select p.id,p.name,p.age,p.idcard from person p,idcard c where p.idcard=c.id
</select>

<select id="selectIdcard" parameterType="int" resultMap="idcards">
select * from idcard where id=#{cid}
</select>

<!-- 定义集合 接收查询所返回的Idcard-->
<resultMap type="Idcard" id="idcards">
<id column="id" property="cid"/>
<result column="idnum" property="idnum"/>
</resultMap>
<!-- 定义集合 接收查询所返回的Person + Idcard-->
<resultMap type="Person" id="persons">
<id column="id" property="pid"/>
<result column="age" property="age"/>
<result column="name" property="name"/>
<!--
association 是用来维护person和idcard关系的,在person类中 有Idcard的对象为属性;
其中的属性包括:
property:person实体类内的Idcard对象
column:数据库表对应的字段
javaType:关联的Java实体类类型
select:通过哪个SQL语句来查询Idcard实体类对应的数据库信息
-->
<association property="idcard" column="idcard"
javaType="Idcard" select="selectIdcard">
</association>
</resultMap>

测试代码:

PersonMap personMap = session.getMapper(PersonMap.class);
List<Person> list = personMap.selectAll();
for(Person p : list){
System.out.println(p);
}


**第二种查询方法:

PersonMapper.xml内的配置:

<select id="selectAll" resultMap="persons">
select p.id,p.name,p.age,p.idcard,c.id,c.idnum from person p,idcard c where p.idcard=c.id
</select>

<resultMap type="Person" id="persons">
<id column="id" property="pid"/>
<result column="age" property="age"/>
<result column="name" property="name"/>
<association property="idcard" column="idcard"
javaType="Idcard">
<!--内部配置了原来的属性-->
<id column="id" property="cid"/>
<result column="idnum" property="idnum"/>
</association>
</resultMap>

第二种查询方法和第一种最大的差别就在于:SQL语句,association配置。
第二种对第一种做了优化,把原来idcard的select查询写在了自己的内部,另外第二种方法少了一个resultMap的声明,
那是因为现在没有其他需求用得到该resultMap集合,所以写在了内部。如果有这方面的需求可以写在外面!!

测试代码和第一种方法一样。

3.1.2 一对一插入数据

<insert id="addPerson" parameterType="Person" keyProperty="pid" useGeneratedKeys="true">
insert into person(age,name,idcard) values(#{age},#{name},#{idcard.cid})
</insert>
<insert id="addIdCard" parameterType="Idcard" keyProperty="cid" useGeneratedKeys="true">
insert into idcard(idnum) values (#{idnum})
</insert>

写插入语句的时候要注意【SQL】语句的书写,是面向对象的操作。
还有就是注意传入的参数类型为实体类,所以在指定主键和主键策略的时候也是要面向对象,写传入实体类的属性,
如: parameterType="Person" keyProperty="pid"
insert into person(age,name,idcard) values(#{age},#{name},#{idcard.cid}) values 里面的参数必须是实体类的属性,不然插入失败

在写测试类的时候要注意:

Idcard idcard = new Idcard();
idcard.setIdnum("123456789");
//要先插入主表 Idcard
personMap.addIdCard(idcard );

Person person = new Person();
person.setAge(30);
person.setName("李二牛");
person.setIdcard(idcard);建立关联关系

personMap.addPerson(person);

3.1.3 一对一修改操作

因为mybatis没有级联操作,所以修改的时候不会级联操作,只需要修改自己想修改的地方就好了,和JDBC一样。

<update id="updatePerson" parameterType="Person">
update person
<set>
<if test="age!=0">age=#{age},</if>
<if test="name!=null">name=#{name}</if>
<if test="idcard!=null">idcard=#{idcard.cid}</if>
</set>
where idcard=#{idcard.cid}面向对象操作
</update>

<update id="updateIdcard" parameterType="Idcard">
update idcard
<set>
<if test="idnum!=null">idnum=#{idnum}</if>面向对象操作
</set>
where id=#{cid}面向对象操作
</update>

3.1.4 一对一删除操作

因为mybatis没有级联操作,所以删除的时候不会级联操作,只需要修改自己想修改的地方就好了,和JDBC一样。

<delete id="deletePerson" parameterType="Person">
delete from person where idcard=#{idcard.cid} 面向对象操作
</delete>
<delete id="deleteIdcard" parameterType="Idcard">
delete from idcard where id=#{cid}面向对象操作
</delete>

测试代码:

Idcard idcard = new Idcard();
idcard.setCid(12);
Person person = new Person();
person.setIdcard(idcard);

personMap.deletePerson(person);要先删除person,后删除idcard

personMap.deleteIdcard(idcard);


3.2 一对多

数据库表:部门表、雇员表

部门表:

Create Table

CREATE TABLE `department` (
`deptid` int(11) NOT NULL auto_increment,
`deptname` varchar(20) character set utf8 NOT NULL default '',
PRIMARY KEY (`deptid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=gbk

雇员表:


Create Table

CREATE TABLE `employee` (
`empid` int(11) NOT NULL auto_increment,
`empname` varchar(20) character set utf8 NOT NULL default '',
`deptid` int(11) NOT NULL,
PRIMARY KEY (`empid`),
KEY `deptid` (`deptid`),
CONSTRAINT `employee_fk` FOREIGN KEY (`deptid`) REFERENCES `department` (`deptid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=gbk

对应实体类:

public class Department {

private int deptId;
private String deptName;

private Set<Employee> emps;

}
public class Employee {

private int empId;
private String empName;
private Department department;
}

部门和雇员的关系是一对多的关系。下面来看对部门表的映射文件的操作。

查询:

<resultMap type="Department" id="depts">
<id column="deptid" property="deptId"/>
<result column="deptname" property="deptName"/>
<!--ofType="Employee"集合中存放的元素类型 column="deptid" 对应的列,就是外键-->
<!-- 这种形式也可以写在外面,如果该集合会被多次使用,建议写内部 -->
<collection property="emps" ofType="Employee" column="deptid">
<id column="empid" property="empId"/>
<result column="empname" property="empName"/>
</collection>
</resultMap>
<!-- 查询,多表查询的时候建议使用外链接查询,效率高 -->
<select id="selectDeptAll" resultMap="depts">
<![CDATA[
select d.deptid,d.deptname,e.empid,e.empname,e.deptid from department d
INNER JOIN employee e ON d.deptid = e.deptid where d.deptid>0
]]>
</select>

添加:

<!-- 添加 -->
<insert id="addDept" keyProperty="deptId" useGeneratedKeys="true" parameterType="Department">
<![CDATA[
insert into department(deptname) values(#{deptName})
]]>
</insert>
<insert id="addEmp" keyProperty="empId" useGeneratedKeys="true" parameterType="Employee">
<![CDATA[
insert into employee(empname,deptid) values(#{empName},#{department.deptId})
]]>
</insert>


测试代码:

//查询
for(Department d : departmentMap.selectDeptAll()){
System.out.println(d);
}
//添加
Department d1 = new Department();
d1.setDeptName("开发部");

Employee e1 = new Employee();
e1.setEmpName("y1");
e1.setDepartment(d1);
Employee e2 = new Employee();
e2.setEmpName("y2");
e2.setDepartment(d1);

departmentMap.addDept(d1);
departmentMap.addEmp(e1);
departmentMap.addEmp(e2);

在添加数据的时候要注意添加的先后数据。


3.3 多对多

用户和组是多对多的关系:
经过分析,数据库表应该设计为:用户表(user)、组信息表(group_info)、用户组组合表(user_group);
user_group为辅助表,不需要设置主键。详细信息:

Create Table

CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(40) default NULL,
`password` varchar(20) default NULL,
`createtime` timestamp NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)


Create Table

CREATE TABLE `group_info` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(40) default NULL,
`createdate` timestamp NULL default CURRENT_TIMESTAMP,
`state` int(1) default '0' COMMENT '0:可见;1:不可见',
PRIMARY KEY (`id`)
)

CREATE TABLE `user_group` (
`user_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
`createdate` timestamp NULL default CURRENT_TIMESTAMP,
KEY `FK_user_group_user_id` (`user_id`),
KEY `FK_user_group_group_id` (`group_id`),
CONSTRAINT `FK_user_group_group_id` FOREIGN KEY (`group_id`) REFERENCES `group_info` (`id`),
CONSTRAINT `FK_user_group_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
)
3.3.1 插入操作

<!-- 插入 -->
<insert id="addGroup" parameterType="Group" keyProperty="groupId" useGeneratedKeys="true">
<![CDATA[
insert into group_info(name) values(#{groupName})
]]>
</insert>
<insert id="addUser" parameterType="User" keyProperty="userId" useGeneratedKeys="true">
<![CDATA[
insert into user(name) values(#{userName})
]]>
</insert>

<!--addUser_Group的参数是一个map集合,集合的key是userId,value是u1.getUserId()【map.put("userId", u1.getUserId());】;这样就把参数传进来了,这种传参方式以后还会有很多-->
<insert id="addUser_Group" parameterType="map">
<![CDATA[
insert into user_group(user_id,group_id) values(#{userId},#{groupId})
]]>
</insert>

测试代码:

User u1 = new User();
u1.setUserName("a1");
User u2 = new User();
u2.setUserName("a2");

groupMap.addUser(u1);
groupMap.addUser(u2);

Group g1 = new Group();
g1.setGroupName("设计部");
groupMap.addGroup(g1);

维护用户和组之间的关系,要分别插入
Map map = new HashMap();
map.put("userId", u1.getUserId());
map.put("groupId",g1.getGroupId());
groupMap.addUser_Group(map );

Map map2 = new HashMap();
map2.put("userId", u2.getUserId());
map2.put("groupId", g1.getGroupId());
groupMap.addUser_Group(map2);

这里重点要说的是:我们在创建对象u1的时候没有给其设置userId,后面还能取到值,是因为程序是顺序执行的,
在执行的过程中mybatis添加u1后,将u1的信息有存储到u1,里面包含了u1的id

3.3.2 删除:

<delete id="deleteGroup" parameterType="int">
<![CDATA[
delete from group_info where id=#{groupId}
]]>
</delete>

<delete id="deleteUserAndGroup" parameterType="int">
<![CDATA[
delete from user_group where group_id=#{groupId}
]]>
</delete>

测试:

groupMap.deleteUserAndGroup(3);
groupMap.deleteGroup(3);

3.3.3 查询:

<!-- 查询 给定组id,查询出组内的所有人和组的信息 -->
<resultMap type="Group" id="groups">
<id column="groupId" property="groupId"/>
<result column="groupName" property="groupName"/>
<collection property="users" javaType="User">
<id column="userId" property="userId"/>
<result column="userName" property="userName"/>
</collection>
</resultMap>
<select id="selectGroup" parameterType="int" resultMap="groups">
<![CDATA[
select g.id as groupId,g.name as groupName,u.id as userId,u.name as userName from group_info g
INNER JOIN user_group ug on g.id = ug.group_id
INNER JOIN user u on ug.user_id=u.id where g.id=#{id};
]]>
</select>

4.注解

注解完成单表的CRUD,mybatis的注解是写在接口上的,这样比较方便开发,不用来回切换文件,还有就是避免了接口和XML文件中的id名相同等问题。

不过,即使使用注解,*Mapper.xml文件还是要配置在Configuration.xml中的。因为后面有一对多的注解操作,如果返回值为集合的时候,

使用注解不太方便,将集合的映射关系配置在XML文件中比较方便,不容易出错。


********使用注解的时候要小心SQL语句内的参数的正确性!!

【注意】:

使用注解前,应当先把接口配置在Configuration.xml中,如下:

<mappers>
<mapper resource="com/mxf/mapper/UserMapper.xml" />
<mapper class="com.mxf.mapper.UserMap"/> ***
</mappers>

4.1.1 添加:

@Insert("INSERT into user(name,password) values(#{userName},#{password})")
@Options(useGeneratedKeys=true,keyProperty="userId")
public void addUser(User user);

注意:keyProperty、values内的参数应该和对象的属性名保持一致

4.1.2 删除:

@Delete("delete from user where id=#{userId}")
public void deleteUserById(@Param("userId")int userId);

注意:SQL中id的参数名称应该和@Param("userId")内的参数名保持一致

4.1.3 更新:

@Update("update user set name=#{userName},password=#{password} where id =#{userId}")
public void updateUser(User user);

4.1.4 查询所有人:

@Select("select id as userId,name as userName from user")
public List<User> selectAllUser();


注意:select id as userId,name as userName from user 如果select语句中的id as userId,name as userName不这样写,查询不出来数据,null

查询中要求和属性名相同

4.1.5 分页查询:

@Select("select u.id as userId,u.name as userName,u.password as password from user u where u.name like #{user.userName} LIMIT #{firstResult},#{maxResult}")
public List<User> selectUser(@Param("user") User user,
@Param("firstResult") int firstResult,
@Param("maxResult") int maxResult);


原文地址:https://www.cnblogs.com/blog411032/p/5320504.html