zoukankan      html  css  js  c++  java
  • 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);


  • 相关阅读:
    通过xshell在本地win主机和远程linux主机传输文件
    CentOS7.4搭建ftp服务
    CentOS7.4中配置jdk环境
    spring AOP学习笔记
    java代码连接oracle数据库的方法
    通过xshell上传和下载文件
    java设计模式简述
    本地项目文件通过git提交到GitHub上
    centos7中oracle数据库安装和卸载
    centos7远程服务器中redis的安装与java连接
  • 原文地址:https://www.cnblogs.com/blog411032/p/5320504.html
Copyright © 2011-2022 走看看