<!--MyBaits依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!--log4j日志依赖-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<!--mysql驱动的坐标-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
数据库表的环境搭建:
javaBean:(封装数据)
public class people {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "people{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Dao接口,操作数据库:
public interface peopleDao {
//按照姓名查询员工
public people getPeoByName(String name);
}
<?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>
<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/tx"/>
<property name="username" value="root"/>
<property name="password" value="126433"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
<?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">
<!--namespace: 名称空间:写接口的全类名,相当于告诉mybaits这个配置文件是实现哪个接口的-->
<mapper namespace="Com.MyBaits.peopleDao">
<!--select: 用来定义一个查询操作
id:方法名,相当于这个配置是对某个方法的实现
resultType:指定方法运行后的返回值类型(查询操作必须指定的),写全类名
#{属性名}:代表取出传递过来的某个参数的值-->
<select id="getPeoByName" resultType="Com.MyBaits.people">
select * from people where name = #{name}
</select>
</mapper>
<?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>
<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/tx"/>
<property name="username" value="root"/>
<property name="password" value="126433"/>
</dataSource>
</environment>
</environments>
<!--引入我们自己编写的每一个接口的实现文件-->
<mappers>
<!--resource: 表示从类路径下找资源-->
<!--如果people.xml放在了peo包下,那么这里路径写peo/people.xml-->
<mapper resource="people.xml"/>
</mappers>
</configuration>
//1.根据全局配置文件创建出一个SqlSessionFactory
//SqlSessionFactory:是Sqlsession工厂,负责创建Sqlsession对象
//Sqlsession:sql会话(代表和数据库的一次会话)
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession();
people dhy;
try{
//3.使用sqlsession操作数据库,获取到dao接口的实现
peopleDao peoDao = sqlSession.getMapper(peopleDao.class);
//4.调用方法
dhy = peoDao.getPeoByName("大忽悠");
}finally {
sqlSession.close();
}
System.out.println(dhy);
完整代码:
public class main {
public static void main(String[] args) throws IOException {
//1.根据全局配置文件创建出一个SqlSessionFactory
//SqlSessionFactory:是Sqlsession工厂,负责创建Sqlsession对象
//Sqlsession:sql会话(代表和数据库的一次会话)
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession();
people dhy;
try{
//3.使用sqlsession操作数据库,获取到dao接口的实现
peopleDao peoDao = sqlSession.getMapper(peopleDao.class);
//4.调用方法
dhy = peoDao.getPeoByName("大忽悠");
}finally {
sqlSession.close();
}
System.out.println(dhy);
}
}
peo接口:
public interface peopleDao {
//按照姓名查询员工
public people getPeoByName(String name);
//更新员工
public boolean updatePeo(people peo);
//删除员工
public Integer deletePeo(people peo);
//插入员工
public Long insertPeo(people peo);
}
people.xml:
<?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">
<!--namespace: 名称空间:写接口的全类名,相当于告诉mybaits这个配置文件是实现哪个接口的-->
<mapper namespace="Com.MyBaits.peopleDao">
<!--select: 用来定义一个查询操作
id:方法名,相当于这个配置是对某个方法的实现
resultType:指定方法运行后的返回值类型(查询操作必须指定的),写全类名
#{属性名}:代表取出传递过来的某个参数的值-->
<select id="getPeoByName" resultType="Com.MyBaits.people">
select * from people where name = #{name}
</select>
<update id="updatePeo">
update people set name=#{name},age=#{age}
where name=#{name}
</update>
<delete id="deletePeo">
delete from people where name=#{name}
</delete>
<insert id="insertPeo">
insert into people values(#{name},#{age})
</insert>
</mapper>
测试主类:
public class main {
static SqlSessionFactory sqlSessionFactory;
//将创建工厂这段重复代码抽取处理,工厂只有一个,但是每次获取连接,都是不同的连接
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
//创建工厂镀锡
initSqlSessionFactory();
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession();
people dhy;
try{
//3.使用sqlsession操作数据库,获取到dao接口的实现(映射器)
peopleDao peoDao = sqlSession.getMapper(peopleDao.class);
//4.调用方法
//1.查询
dhy = peoDao.getPeoByName("大朋友");
//2.增加
Long ins=peoDao.insertPeo(new people("超级大忽悠",19));
//3.修改
boolean ret=peoDao.updatePeo(new people("大忽悠",520));
//4.删除
int del=peoDao.deletePeo(new people("大朋友",20));
System.out.println("增添的结果:"+ins);
System.out.println("修改的结果为:"+ret);
System.out.println("删除的结果为:"+del);
}finally {
//手动提交
sqlSession.commit();
sqlSession.close();
}
System.out.println("查询的结果:"+dhy);
}
}
finally {
//手动提交
sqlSession.commit();
sqlSession.close();
}
SqlSession sqlSession = sqlSessionFactory.openSession(true);
jdbc.properties配置文件:
username=root
password=126433
jdbcurl=jdbc:mysql://localhost:3306/tx
dirverclass=com.mysql.jdbc.Driver
MyBaits-config.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>
<!--和spring的context: property-placeholder;引用外部配置文件-->
<!--
resource:从类路径下开始引用
url:引用磁盘路径或者网络路径的资源
-->
<!--classpath前缀是spring框架才有的-->
<properties resource="jdbc.properties"> </properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--配置连接池-->
<dataSource type="POOLED">
<!--${取出配置文件中的值}-->
<property name="driver" value="${dirverclass}"/>
<property name="url" value="${jdbcurl}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--引入我们自己编写的每一个接口的实现文件-->
<mappers>
<!--resource: 表示从类路径下找资源-->
<!--如果people.xml放在了peo包下,那么这里路径写peo/people.xml-->
<mapper resource="people.xml"/>
</mappers>
</configuration>
<!--类型别名,为常用的类型(javaBean)起别名-->
<typeAliases>
<!--typeAlias:为一个javaBean起别名,
别名默认就是类名(不区分大小写)======》这里的别名默认就是people,使用时不区分大小写,
配置文件中就可以使用别名-->
<!--alias指定别名===》不区分大小写-->
<!-- <typeAlias type="Com.MyBaits.people" alias="peo"/>-->
<!--批量起别名,name=""指定包名,默认别名就是类名-->
<package name="Com.MyBaits"/>
</typeAliases>
@Alias("peo")
public class people {
}
<!--
environments配置环境们
environment :配置一个具体的环境,都需要一个事务管理器和一个数据源
后来数据源,和事务管理都是spring来做
-->
<!--default="development": 默认使用哪个环境-->
<environments default="development">
<!--id="development"是当前环境的唯一标识,这里可以写多个环境,每个环境都有自己的id-->
<environment id="development">
<transactionManager type="JDBC"/>
<!--配置连接池-->
<dataSource type="POOLED">
<!--${取出配置文件中的值}-->
<property name="driver" value="${dirverclass}"/>
<property name="url" value="${jdbcurl}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--mybaits用来考虑数据库移植性的-->
<databaseIdProvider type="DB_VENDOR">
<!--name="":数据库厂商的标识 value:给这个标识起一个好用的名字
常用的数据库产商标识: MySQL Orcale SQL Server
下面操作是起别名-->
<property name="MySQL" value="mysql"/>
<property name="Orcale" value="orcale"/>
<property name="SQL Serve" value="qs"/>
</databaseIdProvider>
使用:
<!--默认这个查询是不区分环境-->
<select id="getPeoByName" resultType="peo">
select * from people where name = #{name}
</select>
<!--如果能精确匹配就精确,不能就模糊-->
<select id="getPeoByName" resultType="peo" databaseId="mysql">
select * from people where name = #{name}
</select>
<!--如果使用orcale数据库,那么走下面的sql语句-->
<select id="getPeoByName" resultType="peo" databaseId="orcale" >
select * from people where name = #{name}
</select>
<!--写好的sql映射文件需要使用mappers注册起来-->
<mappers>
<!--
url:可以从磁盘或者网络路径引用
resource:在类路径下找sql映射文件
class:直接引用接口的全类名
可以将xml文件放在和dao接口同目录下,而且文件名和接口名一致
-->
<mapper resource="people.xml"/>
</mappers>
xml中注册—>使用Dao接口的全类名
<!--写好的sql映射文件需要使用mappers注册起来-->
<mappers>
<!--
url:可以从磁盘或者网络路径引用
resource:在类路径下找sql映射文件
class:直接引用接口的全类名
必须将xml文件放在和dao接口同目录下,而且文件名和接口名一致
-->
<mapper class="Com.MyBaits.peopleDao"/>
</mappers>
Dao接口注解配置:
public interface peopleDao {
//按照姓名查询员工
@Select("select * from people where name = #{name}")
public people getPeoByName(String name);
//更新员工
@Update(" update people set name=#{name},age=#{age},peo_id=#{PeoId}\n" +
"where name=#{name}")
public boolean updatePeo(people peo);
//删除员工
@Delete("delete from people where name=#{name}")
public Integer deletePeo(people peo);
//插入员工
@Insert("insert into people values(#{name},#{age},#{PeoId})")
public Long insertPeo(people peo);
}
测试:
public class main {
static SqlSessionFactory sqlSessionFactory;
//将创建工厂这段重复代码抽取处理,工厂只有一个,但是每次获取连接,都是不同的连接
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
//创建工厂镀锡
initSqlSessionFactory();
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession(true);
people dhy;
try{
//3.使用sqlsession操作数据库,获取到dao接口的实现(映射器)
peopleDao peoDao = sqlSession.getMapper(peopleDao.class);
//4.调用方法
//1.查询
dhy = peoDao.getPeoByName("大朋友");
//2.增加
Long ins=peoDao.insertPeo(new people("超级大忽悠",19,5));
//3.修改
boolean ret=peoDao.updatePeo(new people("大忽悠",520,521));
//4.删除
int del=peoDao.deletePeo(new people("大朋友",20));
System.out.println("增添的结果:"+ins);
System.out.println("修改的结果为:"+ret);
System.out.println("删除的结果为:"+del);
}finally {
//手动提交
/* sqlSession.commit();*/
sqlSession.close();
}
System.out.println("查询的结果:"+dhy);
}
}
<mappers>
<package name="Com.MyBaits"/>
</mappers>
MyBatis注册映射文件(resource、class、package 三者区别)
解决Mybatis中出现的Invalid bound statement (not found)问题
写在pom.xml的bulid标签里面
<!--让IDEA不要忽略src目录下的xml文件-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
当然,如果这里不设置属性,传值的时候写null,mysql也会按照当前主键值往后增加一位进行赋值操作
<!--让mybaits自动的将自增id赋值给传入的employee对象的id属性
useGeneratedKeys="true"
keyProperty="": 将刚才的自增id封装给哪个属性
-->
<insert id="insertPeo" useGeneratedKeys="true" keyProperty="PeoId">
insert into people values(#{name},#{age},#{PeoId})
</insert>
这里是因为之前插入了几次,又删除了
底层是调用原生jdbc获取主键的方法
<insert id="insertPeo" useGeneratedKeys="true" keyProperty="PeoId">
/*
查询主键
order="before"
在核心sql语句之前运行一个查询sql查到id,将查到的id赋值给javaBean的哪个属性
*/
<selectKey order="BEFORE" resultType="java.lang.Integer" keyProperty="PeoId">
select max(peo_id)+1 from people
</selectKey>
insert into people values(#{name},#{age},#{PeoId})
</insert>
public boolean updatePeo(@Param("name") String name,@Param("id") Integer id);
peopleDao接口:
public people getPeoByName(Map<String,Object> map);
测试类:
//1.查询
Map<String,Object> map=new HashMap<String, Object>();
map.put("name","大忽悠");
map.put("age",18);
dhy = peoDao.getPeoByName(map);
peopleDao.xml:
<select id="getPeoByName" resultType="Com.MyBaits.peopleDao.peopleDao">
select * from people where name = #{name} and age=#{age}
</select>
#{属性名}:是参数预编译方式,参数的位置都是由?替代,参数后来都是预编译设置进去的,不会由sql注入的安全问题
${属性名}:不是参数预编译方式,而是直接和sql语句进行拼串,不安全
一般动态获取表名的时候,可以把表名放入map集合中,在xml配置文件中通过${}动态取出表名
peopleDao接口:
public interface peopleDao {
//按照姓名查询员工
public List<people> getPeoByName(Map<String,Object> map);
//更新员工
public boolean updatePeo(people peo);
//删除员工
public Integer deletePeo(people peo);
//插入员工
public Integer insertPeo(people peo);
}
peopleDao.xml:
<select id="getPeoByName" resultType="Com.MyBaits.people">
select * from ${table}
</select>
测试类:
public class main {
static SqlSessionFactory sqlSessionFactory;
//将创建工厂这段重复代码抽取处理,工厂只有一个,但是每次获取连接,都是不同的连接
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
//创建工厂镀锡
initSqlSessionFactory();
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession(true);
List<people> p=new LinkedList<people>();
try{
//3.使用sqlsession操作数据库,获取到dao接口的实现(映射器)
peopleDao peoDao = sqlSession.getMapper(peopleDao.class);
//4.调用方法
//1.查询
Map<String,Object> map=new HashMap<String, Object>();
map.put("table","people");
p = peoDao.getPeoByName(map);
}finally {
//手动提交
/* sqlSession.commit();*/
sqlSession.close();
}
System.out.println("查询的结果:"+p);
}
}
测试主类:
public class main {
static SqlSessionFactory sqlSessionFactory;
//将创建工厂这段重复代码抽取处理,工厂只有一个,但是每次获取连接,都是不同的连接
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
//创建工厂对象
initSqlSessionFactory();
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession(true);
HashMap<Object,Object> p=new HashMap<Object,Object>();
try{
//3.使用sqlsession操作数据库,获取到dao接口的实现(映射器)
peopleDao peoDao = sqlSession.getMapper(peopleDao.class);
//4.调用方法
//1.查询
Map<String,Object> map=new HashMap<String, Object>();
map.put("table","people");
map.put("name","大忽悠");
p=peoDao.getPeoByName(map);
}finally {
//手动提交
/* sqlSession.commit();*/
sqlSession.close();
}
System.out.println("查询的结果:"+p);
}
}
public class main {
static SqlSessionFactory sqlSessionFactory;
//将创建工厂这段重复代码抽取处理,工厂只有一个,但是每次获取连接,都是不同的连接
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
//创建工厂对象
initSqlSessionFactory();
//2.获取和数据库的一次会话:getConnection()
SqlSession sqlSession = sqlSessionFactory.openSession(true);
HashMap<Integer,people> p=new HashMap<Integer,people>();
try{
//3.使用sqlsession操作数据库,获取到dao接口的实现(映射器)
peopleDao peoDao = sqlSession.getMapper(peopleDao.class);
//4.调用方法
//1.查询
Map<String,Object> map=new HashMap<String, Object>();
map.put("table","people");
map.put("name","大忽悠");
p=peoDao.getPeoByName(map);
}finally {
//手动提交
/* sqlSession.commit();*/
sqlSession.close();
}
System.out.println("查询的结果:"+p);
}
}
<!--namespace: 名称空间:写接口的全类名,相当于告诉mybaits这个配置文件是实现哪个接口的-->
<mapper namespace="Com.MyBaits.peopleDao.peopleDao">
<!--resultType="java.util.HashMap":使用默认规则,属性列名一一对应-->
<!-- <select id="getPeoByName" resultType="java.util.HashMap">-->
<!--查出数据封装结果的时候,使用peo自定义的规则-->
<select id="getPeoByName" resultMap="peo">
select * from ${table}
</select>
<!--自定义结果集(resultMap):自己定义每一列的数据和javabean的映射规则-->
<!--
type:指定为哪个javaBean自定义封装规则,全类名
id="":唯一标识,让别名在后面引用
-->
<resultMap id="peo" type="Com.MyBaits.people">
<!--
指定主键列的对应规则
column=“peo_id”:指定哪一列是主键列
property="":指定peopl1的哪个属性封装peo_id这一列数据
-->
<id property="peo_id" column="peo_id"/>
<!--普通列-->
<result property="name" column="name"/>
<result property="age" column="age"/>
</resultMap>
</mapper>
案例: 一个钥匙开一把锁,但是一把锁可以有多个钥匙
Key类:
public class Key {
private Integer id;//钥匙的id
private String keyName;//钥匙的名字
private Lock lock;//一把钥匙对应一把锁
public Key(Integer id, String keyName, Lock lock) {
this.id = id;
this.keyName = keyName;
this.lock = lock;
}
public Key() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
public Lock getLock() {
return lock;
}
public void setLock(Lock lock) {
this.lock = lock;
}
@Override
public String toString() {
return "Key{" +
"id=" + id +
", keyName='" + keyName + '\'' +
", lock=" + lock +
'}';
}
}
lock类:
public class Lock {
private Integer id;//锁的id
private String name;//锁的名字·
public Lock(Integer id, String name) {
this.id = id;
this.name = name;
}
public Lock() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Lock{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
keydao:
public interface keydao {
//将钥匙和锁的信息一起查出来
public Key getKeyById(Integer id);
}
这里选择左外连接
<!--写好的sql映射文件需要使用mappers注册起来-->
<mappers>
<mapper resource="KeyDao.xml"/>
</mappers>
<mapper namespace="Com.MyBaits.KeyDao.keydao">
<!--
下面展示查出来的列:
id keyname lockid lid(这里查询时起别名,是为了给查询出来的两个id做区分) lockName
-->
<select id="getKeyById" resultMap="myKey">
SELECT k.*,l.id lid ,l.lockName FROM `key` k LEFT JOIN `lock` l
ON k.lockid = l.id WHERE k.id= #{id};
</select>
<!--自定义封装规则:使用级联属性封装联合查询出的结果-->
<resultMap id="myKey" type="Com.MyBaits.KeyAndLock.Key">
<id property="id" column="id"/>
<id property="keyName" column="keyName"/>
<id property="lock.id" column="lockid"/>
<id property="lock.name" column="lockName"/>
</resultMap>
</mapper>
主类:
public class main {
static SqlSessionFactory sqlSessionFactory;
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
initSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession(true);
Key k=null;
try{
keydao kd= sqlSession.getMapper(keydao.class);
if(kd==null)
System.out.println("为空");
else
k=kd.getKeyById(2);
}finally {
sqlSession.close();
}
System.out.println("查询的结果:"+k);
}
}
<!--
下面展示查出来的列:
id keyname lockid lid(这里查询时起别名,是为了给查询出来的两个id做区分) lockName
-->
<select id="getKeyById" resultMap="myKey">
SELECT k.*,l.id lid ,l.lockName FROM `key` k LEFT JOIN `lock` l
ON k.lockid = l.id WHERE k.id= #{id};
</select>
<!--自定义封装规则:使用级联属性封装联合查询出的结果-->
<resultMap id="myKey" type="Com.MyBaits.KeyAndLock.Key">
<id property="id" column="id"/>
<id property="keyName" column="keyName"/>
<!--
接下来的属性是一个对象,自定义这个对象的封装规则,使用association: 表示联合了一个对象
javaType:指定这个属性的类型
-->
<association property="lock" javaType="Com.MyBaits.KeyAndLock.Lock">
<!--定义lock属性这个Lock对象如何封装-->
<id property="id" column="lic"/>
<result property="name" column="lockName"/>
</association>
</resultMap>
需求: 查找万能锁,显示其所有钥匙
下面是查询需要的sql语句:
LockDao.xml
<mapper namespace="Com.MyBaits.KeyDao.LockDao">
<select id="getLockById" resultMap="myLock">
SELECT l.*,k.id kid,k.keyName,k.lockid FROM `lock` l
LEFT JOIN `key` k ON l.id=k.lockid WHERE l.id=#{id}
</select>
<!--自定义锁子的封装规则,Lock里面包含一个key的list集合,存放了能开当前锁的所有钥匙-->
<resultMap id="myLock" type="Com.MyBaits.KeyAndLock.Lock">
<id property="id" column="id"/>
<result property="name" column="lockName"/>
<!--第三个属性是一个集合-->
<!--collection定义集合元素的封装
property="":指定哪个属性是集合属性
javaType:指定对象的类型===>association
ofType:指定集合里面元素的类型-->
<collection property="listKey" ofType="Com.MyBaits.KeyAndLock.Key">
<!--标签体中指定集合中这个元素的封装规则-->
<id property="id" column="kid"/>
<result property="keyName" column="keyName"/>
<!--key里面有一个Lock对象,下面使用association完成对Lock对象的封装-->
<association property="lock" javaType="Com.MyBaits.KeyAndLock.Lock">
<id property="id" column="id"/>
<result property="name" column="lockName"/>
</association>
</collection>
</resultMap>
</mapper>
main
public class main {
static SqlSessionFactory sqlSessionFactory;
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
initSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession(true);
Lock k=null;
try{
LockDao kd= sqlSession.getMapper(LockDao.class);
k=kd.getLockById(3);
}finally {
sqlSession.close();
}
System.out.println("锁的ID: "+k.getId());
System.out.println("锁的名字: "+k.getName());
System.out.println("能开当前锁的钥匙:");
LinkedList<Key> list=k.getListKey();
for(Key key:list)
{
System.out.println("锁的编号:"+key.getId());
System.out.println("锁的名字:"+key.getKeyName());
}
}
}
举例:查询钥匙的时候,顺便查出锁子
KeyDao接口:
public interface KeyDao {
public Key getKeyById(Integer id);
}
KeyDao接口的实现: KeyDao.xml
<?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.MyBaits.KeyDao.KeyDao">
<!--id keyName lockid-->
<!--查询key的时候带上锁子的信息-->
<select id="getKeyById" resultMap="myLock">
select* from `key` where id= #{id}
</select>
<!--这里的type是为哪一个javaBean自定义类型封装规则-->
<resultMap id="myLock" type="Com.MyBaits.KeyAndLock.Key">
<id property="id" column="id"/>
<result property="keyName" column="keyName"/>
<!--告诉mybaits自己去调用一个查询查锁子,
select=“”:指定一个查询sql的唯一标识,mybatis自动调用指定的sql查出lock封装进来
告诉mybaits把哪一列的值传递过去
column:指定将哪一列的数据传递过去
会将返回的查到的lock对象数据封装到lock对象里面-->
<!--这里上面两个属性封装完之后,要封装lock对象属性,是通过再调用一个方法查询到我们需要的lock对象,封装到这里的lock里面-->
<association property="lock" select="Com.MyBaits.KeyDao.LockDao.getLockById" column="lockid"></association>
</resultMap>
</mapper>
LockDao接口:
public interface LockDao {
public Lock getLockById(Integer id);
}
LockDao接口的是实现:LockDao.xml
<?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.MyBaits.KeyDao.LockDao">
<!--查询锁子的方法-->
<select id="getLockById" resultType="Com.MyBaits.KeyAndLock.Lock">
SELECT l.id,l.lockName `name` FROM `lock` l WHERE id=#{id}
</select>
</mapper>
两个接口的实现的.xml文件进行注册:
<!--写好的sql映射文件需要使用mappers注册起来-->
<mappers>
<mapper resource="KeyDao.xml"/>
<mapper resource="LockDao.xml"/>
</mappers>
主类:
public class main {
static SqlSessionFactory sqlSessionFactory;
static public void initSqlSessionFactory() throws IOException {
String resource = "MyBaits-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static void main(String[] args) throws IOException {
initSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession(true);
Key k=null;
try{
KeyDao kd= sqlSession.getMapper(KeyDao.class);
k=kd.getKeyById(1);
}finally {
sqlSession.close();
}
System.out.println(k);
}
}
<?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>
<properties resource="jdbc.properties"> </properties>
<settings>
<!--开启延迟加载开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--开启属性按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--配置连接池-->
<dataSource type="POOLED">
<!--${取出配置文件中的值}-->
<property name="driver" value="${dirverclass}"/>
<property name="url" value="${jdbcurl}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--写好的sql映射文件需要使用mappers注册起来-->
<mappers>
<mapper resource="KeyDao.xml"/>
<mapper resource="LockDao.xml"/>
</mappers>
</configuration>
<?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.MyBaits.KeyDao.KeyDao">
<!--id keyName lockid-->
<!--查询key的时候带上锁子的信息-->
<select id="getKeyById" resultMap="myLock">
select* from `key` where id= #{id}
</select>
<!--这里的type是为哪一个javaBean自定义类型封装规则-->
<resultMap id="myLock" type="Com.MyBaits.KeyAndLock.Key">
<id property="id" column="id"/>
<result property="keyName" column="keyName"/>
<!--告诉mybaits自己去调用一个查询查锁子,
select=“”:指定一个查询sql的唯一标识,mybatis自动调用指定的sql查出lock封装进来
告诉mybaits把哪一列的值传递过去
column:指定将哪一列的数据传递过去
会将返回的查到的lock对象数据封装到lock对象里面-->
<!--这里上面两个属性封装完之后,要封装lock对象属性,是通过再调用一个方法查询到我们需要的lock对象,封装到这里的lock里面-->
<association property="lock" select="Com.MyBaits.KeyDao.LockDao.getLockById"
column="lockid" fetchType="lazy"></association>
</resultMap>
</mapper>
Key类:
public class Key {
private Integer id;//钥匙的id
private String keyName;//钥匙的名字
@Override
public String toString() {
return "Key{" +
"id=" + id +
", keyName='" + keyName + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
}
KeyDao接口:
public interface KeyDao {
public Key getKeyById(Integer id);
}
KeyDao.xml:
<?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.MyBaits.KeyDao.KeyDao">
<!--查询钥匙的信息-->
<select id="getKeyById" resultType="Com.MyBaits.KeyAndLock.Key">
select* from `key` where lockid= #{id}
</select>
</mapper>
Lock类:
public class Lock {
private Integer id;//锁的id
private String name;//锁的名字·
private LinkedList<Key> KeyList;
@Override
public String toString() {
return "Lock{" +
"id=" + id +
", name='" + name + '\'' +
", KeyList=" + KeyList +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LinkedList<Key> getKeyList() {
return KeyList;
}
public void setKeyList(LinkedList<Key> keyList) {
KeyList = keyList;
}
}
LockDao接口:
public interface LockDao {
public Lock getLockById(Integer id);
}
LockDao.xml
<?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.MyBaits.KeyDao.LockDao">
<!--
这里采用分步查询,先查出锁的信息,再查出能开这把锁的所有钥匙的信息
-->
<select id="getLockById" resultMap="myLock">
SELECT l.id,l.lockName `name` FROM `lock` l WHERE id=#{id}
</select>
<resultMap id="myLock" type="Com.MyBaits.KeyAndLock.Lock">
<id property="id" column="id"/>
<result property="name" column="lockName"/>
<!--第三个属性是一个集合,采用collection对集合进行封装-->
<!--前面加上namespace限定是哪一个类的哪一个方法-->
<!--column把从数据库中查出的那一列的值作为参数,传递给对应的方法-->
<collection property="KeyList"
select="Com.MyBaits.KeyDao.KeyDao.getKeyById"
column="id" fetchType="lazy"/>
</resultMap>
</mapper>
MyBaits-config.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>
<properties resource="jdbc.properties"> </properties>
<settings>
<!--开启延迟加载开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--开启属性按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--配置连接池-->
<dataSource type="POOLED">
<!--${取出配置文件中的值}-->
<property name="driver" value="${dirverclass}"/>
<property name="url" value="${jdbcurl}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--写好的sql映射文件需要使用mappers注册起来-->
<mappers>
<mapper resource="KeyDao.xml"/>
<mapper resource="LockDao.xml"/>
</mappers>
</configuration>