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);


  • 相关阅读:
    Codeforces Gym 100571A A. Cursed Query 离线
    codeforces Gym 100500 J. Bye Bye Russia
    codeforces Gym 100500H H. ICPC Quest 水题
    codeforces Gym 100500H A. Potion of Immortality 简单DP
    Codeforces Gym 100500F Problem F. Door Lock 二分
    codeforces Gym 100500C D.Hall of Fame 排序
    spring data jpa 创建方法名进行简单查询
    Spring集成JPA提示Not an managed type
    hibernate配置文件中的catalog属性
    SonarLint插件的安装与使用
  • 原文地址:https://www.cnblogs.com/blog411032/p/5320504.html
Copyright © 2011-2022 走看看