MyBatis的增删改之后,一定要提交事物!!!
在MySQL中有个特殊的规定,即不允许使用列别名作为查询条件。
一个主人可以养很多条小狗狗,但是一条狗只有一个主人。那主键肯定只能放在dog表里面。
public class Dog {
private int id;
private String name;
private Host host;
...
}
public class Host {
private int HOST_ID;
private String HOST_NAME;
private List<Dog> HOST_DOGS;
...
}
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cj.dao.DogDao">
<select id="QueryById" resultMap="dogMapping">
select d.*,h.* from dog d left join host h on d.DOG_HOST_ID=h.HOST_ID where d.DOG_ID=#{id}
</select>
<resultMap id="dogMapping" type="com.cj.entity.Dog">
<id column="DOG_ID" property="id"></id>
<result column="DOG_NAME" property="name"></result>
<!-- 级联封装-->
<!-- <result property="DOG_HOST.HOST_ID" column="DOG_HOST_ID"></result>-->
<!-- <result property="DOG_HOST.HOST_NAME" column="HOST_NAME"></result>-->
<!-- 用javaType指定javaBean的类型-->
<association property="host" javaType="com.cj.entity.Host">
<id property="HOST_ID" column="HOST_ID"></id>
<result property="HOST_NAME" column="HOST_NAME"></result>
</association>
</resultMap>
</mapper>
public interface DogDao {
/**
* 查询dog表中的主键, 返回单个dog对象
* @param id
* @return
*/
public Dog QueryById(Integer id);
}
@Test
public void test08() throws IOException {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession(); //增删改需要设置自动提交, 查询不需要手动设置
DogDao dogDao = sqlSession.getMapper(DogDao.class);
Dog dog = dogDao.QueryById(2);
System.out.println(dog);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cj.dao.HostDao">
<select id="QueryByUnionId" resultMap="hostMapping">
select h.*,d.* from host h,dog d where h.HOST_ID=d.DOG_HOST_ID and d.DOG_HOST_ID=#{id};
</select>
<resultMap id="hostMapping" type="com.cj.entity.Host">
<id property="HOST_ID" column="HOST_ID"></id>
<result property="HOST_NAME" column="HOST_NAME"></result>
<!-- 用ofType指定集合的泛型-->
<collection property="HOST_DOGS" ofType="com.cj.entity.Dog">
<id property="DOG_ID" column="DOG_ID"></id>
<result property="DOG_NAME" column="DOG_NAME"></result>
</collection>
</resultMap>
</mapper>
public interface HostDao {
/**
* 查询dog表中的hostId返回host列表
* @param id
* @return
*/
public List<Host> QueryByUnionId(Integer id);
}
@Test
public void test09() throws IOException {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession(); //增删改需要设置自动提交, 查询不需要手动设置
HostDao hostDao = sqlSession.getMapper(HostDao.class);
List<Host> hosts = hostDao.QueryByUnionId(1);
System.out.println(hosts);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
对于分步查询,MyBatis框架能对性能进行优化,以后多用分步查询吧!
全局配置文件中开启延迟加载和按需加载:
<configuration>
<settings>
<!-- 开启延迟加载开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 开启属性按需加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
...
</configuration>
public interface DogDao {
/**
* 查询dog表中的主键, 返回单个dog对象
*
* @param id
* @return
*/
public Dog QueryById(Integer id);
/**
* 分步查询第一步
*
* @param id
* @return
*/
public Dog QuerySimple(Integer id);
}
public interface HostDao {
/**
* 查询dog表中的hostId返回host列表
*
* @param id
* @return
*/
public List<Host> QueryByUnionId(Integer id);
/**
* 分步查询第二步
*
* @param id
* @return
*/
public Host QuerySimple(Integer id);
}
<select id="QuerySimple" resultMap="simpleMapping">
select * from dog where DOG_ID=#{id}
</select>
<resultMap id="simpleMapping" type="com.cj.entity.Dog">
<id property="DOG_ID" column="DOG_ID"></id>
<result property="DOG_NAME" column="DOG_NAME"></result>
<!-- select标签指定已经查询出来的host对象, column标签指定传入的参数(第一步查询已经查出来的DOG_HOST_ID)-->
<association property="DOG_HOST" select="com.cj.dao.HostDao.QuerySimple" column="DOG_HOST_ID"></association>
</resultMap>
<select id="QuerySimple" resultType="com.cj.entity.Host">
select * from host where HOST_ID=#{id}
</select>
public class Person {
private Integer PERSON_ID;
private String PERSON_NAME;
private Integer PERSON_GENDER;
private Integer PERSON_AGE;
...
}
public interface PersonDao {
public Person Query(Integer id, String name);
}
<select id="Query" resultType="com.cj.entity.Person">
select * from person
<where>
-- 因为传入了多个参数, 所以用paramn取参数, 当传入POJO的时候, 直接用成员变量取值
<if test="param1!=null and !''.equals(param1)">
-- 只有if没有else, 想用else的情况需要用choose标签
and PERSON_ID=#{param1}
</if>
<if test="param2!=null and !''.equals(param2)">
and PERSON_NAME=#{param2}
</if>
</where>
</select>
@Test
public void test11() throws IOException {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession(); //增删改需要设置自动提交, 查询不需要手动设置
PersonDao personDao = sqlSession.getMapper(PersonDao.class);
Person person = personDao.Query(2, "越前龙马");
System.out.println(person);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
public interface PersonDao {
public Person Query(Integer id, String name);
//@Param注解指定参数名
public List<Person> QueryByListId(@Param("ids") List<Integer> ids);
...
}
<select id="QueryByListId" resultType="com.cj.entity.Person">
select * from person
<where>
PERSON_ID in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</where>
</select>
@Test
public void test12() throws IOException {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession(); //增删改需要设置自动提交, 查询不需要手动设置
PersonDao personDao = sqlSession.getMapper(PersonDao.class);
List<Person> persons = personDao.QueryByListId(Arrays.asList(1, 2));
System.out.println(persons);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
测试结果:
小结:
foreach 标签的separator属性指定分隔符,并且会自动删除某位的分隔符。collection属性指定遍历的集合。
public interface PersonDao {
public Person Query(Integer id, String name);
//@Param注解指定参数名
public List<Person> QueryByListId(@Param("ids") List<Integer> ids);
public int Update(Person person);
}
<update id="Update">
update person
<set>
<if test="PERSON_NAME!=null and !''.equals(PERSON_NAME)">
PERSON_NAME=#{PERSON_NAME},
</if>
<if test="PERSON_GENDER!=null and !''.equals(PERSON_GENDER)">
PERSON_GENDER=#{PERSON_GENDER},
</if>
<if test="PERSON_AGE!=null and !''.equals(PERSON_AGE)">
PERSON_AGE=#{PERSON_AGE},
</if>
</set>
<where>
PERSON_ID=#{PERSON_ID}
</where>
</update>
@Test
public void test13() throws IOException {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession(true); //增删改需要设置自动提交, 查询不需要手动设置
PersonDao personDao = sqlSession.getMapper(PersonDao.class);
Person person = new Person(2, "越前", 1, null);
int i = personDao.Update(person);
System.out.println(i);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
测试结果:
小结:
set标签会自动删除末尾的逗号,set标签结合if标签可以完成全字段更新引发的问题,替代了ModelAttribute注解!
要想将MyBatis更新数据的返回值设置为受影响的行数,则需要在URL中加上&useAffectedRows=true
。究其根源其实&
在xml中无法使用的,需要用转译字符&
。