标签:factor use ids instance save sfb sep 基本类型 cas
ibatis 亲爹 apache 后爹 google 后后爹github
开源的持久层框架
jdbc 代码繁琐 手写sql 速度快,性能好 就是麻烦
编程步骤
1、导包
2、添加mybatis配置文件
3、写实体类
4、写映射文件,修改配置文件,指定英文文件的位置
5、调用mybatis 提供的API SqlSession 提供的方法来访问数据库
1、导包
mybatis
mysql
2、配置文件
<?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> <!-- 环境:配置mybatis的环境 --> <environments default="environment"> <!-- 环境变量:可以配置多个环境变量,比如使用多数据源时,就需要配置多个环境变量 --> <environment id="environment"> <!-- 事务管理器 --> <transactionManager type="JDBC"></transactionManager> <!-- 数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://172.29.12.158:3306/test?useUnicode=true&characterEncoding=utf8"/> <property name="username" value="zongxuan"/> <property name="password" value="zongxuan"/> </dataSource> </environment> </environments> <!-- 映射器:指定映射文件或者映射类 --> <mappers> <mapper resource="entity/MepMapper.xml"/> </mappers> </configuration>
3、实体类的属性名与表的字段表要求一样 大小写无所谓
package entity; public class Emp { private Integer id; private String name; private Double age; 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 Double getAge() { return age; } public void setAge(Double age) { this.age = age; } @Override public String toString() { return "Emp [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
4、写实体类
<?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="test"> <!-- id 唯一 parameterType 参数类型 #{} 实体类的属性 --> <insert id="save" parameterType="entity.Emp"> INSERT INTO emp2(name,age) VALUES(#{name},#{age}) </insert> <!-- resultType:返回结果的类型 最终的 --> <select id="findAll" resultType="entity.Emp"> SELECT * FROM emp2 </select> <select id="findById" parameterType="int" resultType="entity.Emp"> SELECT * FROM emp2 WHERE id=#{id} </select> <update id="modify" parameterType="entity.Emp"> UPDATE emp2 SET name=#{name},age=#{age} WHERE id=#{id} </update> <delete id="delete" parameterType="int"> DELETE FROM emp2 WHERE id=#{id} </delete> </mapper>
5、调用mybatis
package testCase; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import entity.Emp; public class TestMybats { private SqlSession ss; @Before public void init() { SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); SqlSessionFactory ssf = ssfb.build(TestMybats.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml")); ss = ssf.openSession(); } @Test public void t1() { Emp emp = new Emp(); emp.setName("李四"); emp.setAge(new Double("22")); ss.insert("test.save", emp); ss.commit(); ss.close(); } @Test public void t2() { List<Emp> emps = ss.selectList("test.findAll"); System.out.println(emps); ss.close(); } @Test public void t3() { Emp emp = ss.selectOne("test.findById", 4); System.out.println(emp); ss.close(); } @Test public void t4() { Emp emp = ss.selectOne("test.findById", 4); emp.setName("王五"); ss.update("test.modify", emp); ss.commit(); ss.close(); } @Test public void t5() { ss.delete("test.delete", 1); ss.commit(); ss.close(); } }
返回Map类型的结果
mybatis 会将查询结果先封装到一个map对象里面 字段名作为key 字段值作为value
然后再将map对象中的数据添加到实体对象里面
<select id="findById2" parameterType="int" resultType="map"> SELECT * FROM dept WHERE id=#{id} </select>
@Test public void t6() { Map data = ss.selectOne("dept.findById2",3); System.out.println(data); System.out.println(data.get("dname")); ss.close(); }
属性名和字段名不一样
1、在mybatis 映射文件SQL 中使用别名
2、使用ResultMap
1
2、
CREATE TABLE `emp2` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
package entity; public class Emp2 { private Integer emapNo; private String ename; private Double age; public Integer getEmapNo() { return emapNo; } public void setEmapNo(Integer emapNo) { this.emapNo = emapNo; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Double getAge() { return age; } public void setAge(Double age) { this.age = age; } @Override public String toString() { return "Emp2 [emapNo=" + emapNo + ", ename=" + ename + ", age=" + age + "]"; }
}
<!-- 使用ResultMap 解决表的字段名和实体类的属性名不一致的情况 --> <!-- 处理表的字段名和实体类的属性名的对应关系 --> <resultMap type="entity.Emp2" id="emp2Map"> <result property="ename" column="name" /> <result property="emapNo" column="id" /> </resultMap> <select id="findById2" parameterType="int" resultMap="emp2Map"> SELECT * FROM emp2 WHERE id=#{id} </select>
@Test public void t6() { Emp2 emp = ss.selectOne("test.findById2",3); System.out.println(emp); ss.close(); }
Mapper 映射器
符合映射文件的接口
mybatis 会自动实现一个符合该接口要求的对象
要求:
a、接口方法的名称与映射中的sql的id要一样
b、方法的参数类型要与映射文件中的parameterType一致
c、方法的返回类型要与映射文件当中的resultType一致
映射文件的命名空间namespace要等于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> <!-- 环境:配置mybatis的环境 --> <environments default="environment"> <!-- 环境变量:可以配置多个环境变量,比如使用多数据源时,就需要配置多个环境变量 --> <environment id="environment"> <!-- 事务管理器 --> <transactionManager type="JDBC"></transactionManager> <!-- 数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://172.29.12.158:3306/test?useUnicode=true&characterEncoding=utf8"/> <property name="username" value="zongxuan"/> <property name="password" value="zongxuan"/> </dataSource> </environment> </environments> <!-- 映射器:指定映射文件或者映射类 --> <mappers> <mapper resource="entity/EmpMapper.xml"/> </mappers> </configuration>
package com.stevezong.mybatis.entity.dao; import java.util.List; import java.util.Map; import entity.Emp; import entity.Emp2; /** * Mapper映射器 就是一个接口 * * @author steve * */ public interface EmpDAO { void save(Emp emp); List<Emp> findAll(); Emp findById(int id); void delete(int id); void modify(Emp emp); Emp2 findById2(int id); }
<?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.stevezong.mybatis.entity.dao.EmpDAO"> <!-- id 唯一 parameterType 参数类型 #{} 实体类的属性 --> <insert id="save" parameterType="entity.Emp"> INSERT INTO emp2(name,age) VALUES(#{name},#{age}) </insert> <!-- resultType:返回结果的类型 最终的 --> <select id="findAll" resultType="entity.Emp"> SELECT * FROM emp2 </select> <select id="findById" parameterType="int" resultType="entity.Emp"> SELECT * FROM emp2 WHERE id=#{id} </select> <update id="modify" parameterType="entity.Emp"> UPDATE emp2 SET name=#{name},age=#{age} WHERE id=#{id} </update> <delete id="delete" parameterType="int"> DELETE FROM emp2 WHERE id=#{id} </delete> <!-- 使用ResultMap 解决表的字段名和实体类的属性名不一致的情况 --> <!-- 处理表的字段名和实体类的属性名的对应关系 --> <!-- property对应javabean的属性名,column对应数据库字段名 --> <resultMap type="entity.Emp2" id="emp2Map"> <result property="ename" column="name" /> <result property="emapNo" column="id" /> </resultMap> <select id="findById2" parameterType="int" resultMap="emp2Map"> SELECT * FROM emp2 WHERE id=#{id} </select> </mapper>
package testCase; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.stevezong.mybatis.entity.dao.EmpDAO; import entity.Emp; import entity.Emp2; public class TestCase { private SqlSession ss; @Before public void init() { SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); SqlSessionFactory ssf = ssfb.build(TestCase.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml")); ss = ssf.openSession(); } @Test public void t1() { /** * getMapper 方法返回一个符合Mapper映射器(EmpDAO)要求的对象 * */ EmpDAO dao = ss.getMapper(EmpDAO.class); Emp emp = new Emp(); emp.setName("王八"); emp.setAge(new Double(22)); dao.save(emp); ss.commit(); List<Emp> emps = dao.findAll(); System.out.println(emps); Emp emp2 = dao.findById(4); System.out.println(emp2); dao.delete(2); ss.commit(); Emp emp3 = new Emp(); emp3.setName("丽丽"); emp3.setAge(new Double(88)); emp3.setId(10); dao.modify(emp3); ss.commit(); Emp2 emp4 = dao.findById2(3); System.out.println(emp4); ss.close(); } }
spring 集成 mybatis
1、导包
spring-webmvc
mybatis
mybatis-spring
spring-jdbc
mysql
dbcp(c3p0)
2、添加spring的配置文件
mybatis 的配置信息可以添加到spring的配置文件中
3、实体类
entity
4、映射文件
XML
5、Mapper映射器
DAO接口
6、在spring 的配置文件当中,添加MapperScannerConfigurer bean 该bean 负责条用SqlSession的getMapper方法
创建符合Mapper映射器要求的对象,
该bean会将这个对象添加到spring容器里面(默认额id 是首字母小写之后的接口名,也可以在Mapper使用@Rerspository来设定id)
1、
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.stevezong</groupId> <artifactId>mybataiszx</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.44</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>3.2.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.2.8.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>commons-DBCP</groupId> <artifactId>commons-DBCP</artifactId> <version>1.4</version> </dependency> </dependencies> </project>
2
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <!-- mysql 信息 --> <util:properties id="dbInfo"> <prop key="user">zongxuan</prop> <prop key="password">zongxuan</prop> <prop key="url">jdbc:mysql://172.29.12.158:3306/test?useUnicode=true&characterEncoding=utf8 </prop> <prop key="driver">com.mysql.jdbc.Driver</prop> <prop key="initialSize">10</prop> <prop key="maxActive">500</prop> </util:properties> <!-- 配置连接池 --> <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="#{dbInfo.driver}"></property> <property name="url" value="#{dbInfo.url}"></property> <property name="username" value="#{dbInfo.user}"></property> <property name="password" value="#{dbInfo.password}"></property> <property name="initialSize" value="#{dbInfo.initialSize}"></property> <property name="maxActive" value="#{dbInfo.maxActive}"></property> </bean> <!-- 配置SqlSessionFactoryBean mybatis-spring包中 spring 集成mybatis 不在需要mybatis 的配置文件,(使用SqlSessionFactoryBean来代替mybatis的配置文件) --> <bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入连接池, 不再使用mybatis 自带的连接池,而是使用spring管理的连接池 --> <property name="dataSource" ref="ds"></property> <property name="mapperLocations" value="classpath:entity/*.xml"></property> </bean> <!-- 配置MapperScannerConfigurer 负责扫描指定包下面的所有的Mapper映射器然后生成符合这些映射器要求的对象 其实,就是调用SqlSession的getMapper方法 另外,还会将这个对象添加到spring容器里面 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 指定Mapper映射器所在的包 --> <property name="basePackage" value="dao"></property> <!-- 只扫描特定的接口 自己开发注解 自动扫描包下所有接口 遇到带注解标记的将对应对象注册 不加不注解 不会注册 --> <property name="annotationClass" value="annotations.MyBatisRepository"></property> </bean> </beans>
3
package entity; public class Emp { private Integer id; private String name; private Double age; 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 Double getAge() { return age; } public void setAge(Double age) { this.age = age; } @Override public String toString() { return "Emp [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
4
<?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="dao.EmpDAO"> <!-- id 唯一 parameterType 参数类型 #{} 实体类的属性 --> <insert id="save" parameterType="entity.Emp"> INSERT INTO emp2(name,age) VALUES(#{name},#{age}) </insert> <!-- resultType:返回结果的类型 最终的 --> <select id="findAll" resultType="entity.Emp"> SELECT * FROM emp2 </select> <select id="findById" parameterType="int" resultType="entity.Emp"> SELECT * FROM emp2 WHERE id=#{id} </select> <update id="modify" parameterType="entity.Emp"> UPDATE emp2 SET name=#{name},age=#{age} WHERE id=#{id} </update> <delete id="delete" parameterType="int"> DELETE FROM emp2 WHERE id=#{id} </delete> <!-- 使用ResultMap 解决表的字段名和实体类的属性名不一致的情况 --> <!-- 处理表的字段名和实体类的属性名的对应关系 --> <resultMap type="entity.Emp2" id="emp2Map"> <result property="ename" column="name" /> <result property="emapNo" column="id" /> </resultMap> <select id="findById2" parameterType="int" resultMap="emp2Map"> SELECT * FROM emp2 WHERE id=#{id} </select> </mapper>
5
package dao; import java.util.List; import java.util.Map; import annotations.MyBatisRepository; import entity.Emp; import entity.Emp2; /** * Mapper映射器 就是一个接口 * @author steve * */ @MyBatisRepository public interface EmpDAO { void save(Emp emp); List<Emp> findAll(); Emp findById(int id); void delete(int id); void modify(Emp emp); Emp2 findById2(int id); } package annotations; public @interface MyBatisRepository { }
package test; import java.util.List; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import dao.EmpDAO; import entity.Emp; public class TestCase { private ApplicationContext ac; private EmpDAO dao; @Before public void init() { ac = new ClassPathXmlApplicationContext("applicationContext.xml"); dao = ac.getBean("empDAO", EmpDAO.class); } @Test public void t1() { List<Emp> emps = dao.findAll(); System.out.println(emps); } @Test public void t2() { Emp emp = dao.findById(5); System.out.println(emp); } }
6
mybatis 关联映射
将数据库中有关联关系的表 以实体对象引用的方法体现出来
如:在User 有Book
class User{
private List<Book> books;
}
class Book{
private User user;
}
关联的方式:
关联单个对象
Book 中
关联多个对象
User 中
在业务需要对数据库进行关联查询的时候
可以通过一条sql 语句完成关联查询,也可以通过两条sql语句进行关联查询
使用一条语句完成 语句复杂,配置简单 与数据库交互一次
使用两条语句完成 语句简单,配置复杂 与数据库交互两次
1、实体类
2、定义Dao接口
配置Mapper
关联多个对象
1、
package com.stevezong.cloud_note.entity; import java.io.Serializable; import java.util.List; /* * 类属性名和属性数据类型 * 与数据库中的保持一致 * */ public class User implements Serializable { private String cn_user_id; private String cn_user_name; private String cn_user_password; private String cn_user_token; private String cn_user_nick; private List<Book> books; public String getCn_user_id() { return cn_user_id; } public void setCn_user_id(String cn_user_id) { this.cn_user_id = cn_user_id; } public String getCn_user_name() { return cn_user_name; } public void setCn_user_name(String cn_user_name) { this.cn_user_name = cn_user_name; } public String getCn_user_password() { return cn_user_password; } public void setCn_user_password(String cn_user_password) { this.cn_user_password = cn_user_password; } public String getCn_user_token() { return cn_user_token; } public void setCn_user_token(String cn_user_token) { this.cn_user_token = cn_user_token; } public String getCn_user_nick() { return cn_user_nick; } public void setCn_user_nick(String cn_user_nick) { this.cn_user_nick = cn_user_nick; } public List<Book> getBooks() { return books; } public void setBooks(List<Book> books) { this.books = books; } @Override public String toString() { return "User [cn_user_id=" + cn_user_id + ", cn_user_name=" + cn_user_name + ", cn_user_password=" + cn_user_password + ", cn_user_token=" + cn_user_token + ", cn_user_nick=" + cn_user_nick + ", books=" + books + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((books == null) ? 0 : books.hashCode()); result = prime * result + ((cn_user_id == null) ? 0 : cn_user_id.hashCode()); result = prime * result + ((cn_user_name == null) ? 0 : cn_user_name.hashCode()); result = prime * result + ((cn_user_nick == null) ? 0 : cn_user_nick.hashCode()); result = prime * result + ((cn_user_password == null) ? 0 : cn_user_password.hashCode()); result = prime * result + ((cn_user_token == null) ? 0 : cn_user_token.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (books == null) { if (other.books != null) return false; } else if (!books.equals(other.books)) return false; if (cn_user_id == null) { if (other.cn_user_id != null) return false; } else if (!cn_user_id.equals(other.cn_user_id)) return false; if (cn_user_name == null) { if (other.cn_user_name != null) return false; } else if (!cn_user_name.equals(other.cn_user_name)) return false; if (cn_user_nick == null) { if (other.cn_user_nick != null) return false; } else if (!cn_user_nick.equals(other.cn_user_nick)) return false; if (cn_user_password == null) { if (other.cn_user_password != null) return false; } else if (!cn_user_password.equals(other.cn_user_password)) return false; if (cn_user_token == null) { if (other.cn_user_token != null) return false; } else if (!cn_user_token.equals(other.cn_user_token)) return false; return true; } }
2
package com.stevezong.cloud_note.dao; import com.stevezong.cloud_note.entity.User; public interface RelationDao { public User fundUserAndBooks(String userId); }
package com.stevezong.cloud_note.dao; import com.stevezong.cloud_note.entity.User; public interface RelationDao { public User findUserAndBooks(String userId); }
<!----------------------------------------------------------------------------------------------------------------------------------------- --> <!-- 使用两条sql 语句加载数据 --> <select id="findUserAndBooks" parameterType="String" resultMap="userMap1"> SELECT * FROM cn_user WHERE cn_user_id=#{userId} </select> <resultMap id="userMap1" type="com.stevezong.cloud_note.entity.User"> <id property="cn_user_id" column="cn_user_id" /> <result property="cn_user_name" column="cn_user_name" /> <!-- 指定books属性 是一个list集合 返回类型 泛型类型 外键 --> <collection property="books" javaType="java.util.List" ofType="com.stevezong.cloud_note.entity.Book" select="findBooks" column="cn_user_id"> </collection> </resultMap> <select id="findBooks" parameterType="String" resultType="com.stevezong.cloud_note.entity.Book"> SELECT * FROM cn_notebook WHERE cn_user_id=#{userId} </select> <!----------------------------------------------------------------------------------------------------------------------------------------- --> <!-- 一条sql加载User --> <select id="findUserAndBooks1" parameterType="String" resultMap="userMap2"> SELECT * FROM cn_user u JOIN cn_notebook b ON(u.cn_user_id=b.cn_user_id) WHERE u.cn_user_id=#{userId} </select> <resultMap id="userMap2" type="com.stevezong.cloud_note.entity.User"> <!-- 定义cn_user 字段装在,不能省略 --> <id property="cn_user_id" column="cn_user_id" /> <result property="cn_user_name" column="cn_user_name" /> <result property="cn_user_password" column="cn_user_password" /> <result property="cn_user_token" column="cn_user_token" /> <result property="cn_user_nick" column="cn_user_nick" /> <collection property="books" javaType="java.util.List" ofType="com.stevezong.cloud_note.entity.Book"> <id property="cn_notebook_id" column="cn_notebook_id" /> <result property="cn_user_id" column="cn_user_id" /> <result property="cn_notebook_type_id" column="cn_notebook_type_id" /> <result property="cn_notebook_name" column="cn_notebook_name" /> <result property="cn_notebook_desc" column="cn_notebook_desc" /> <result property="cn_notebook_createtime" column="cn_notebook_createtime" /> </collection> </resultMap> <!----------------------------------------------------------------------------------------------------------------------------------------- -->
@Test public void t1() { User user = dao.findUserAndBooks("48595f52-b22c-4485-9244-f4004255b972"); //User user = dao.findUserAndBooks1("48595f52-b22c-4485-9244-f4004255b972"); System.out.println(user); System.out.println(user.getCn_user_name()); System.out.println(user.getBooks().size()); for(Book sub:user.getBooks()) { System.out.println(sub); } }
关联单个对象
通过查询笔记信心,关联用户信息
package com.stevezong.cloud_note.entity; import java.io.Serializable; import java.sql.Timestamp; public class Book implements Serializable { private String cn_notebook_id; private String cn_user_id; private String cn_notebook_type_id; private String cn_notebook_name; private String cn_notebook_desc; private Timestamp cn_notebook_createtime; private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String getCn_notebook_id() { return cn_notebook_id; } public void setCn_notebook_id(String cn_notebook_id) { this.cn_notebook_id = cn_notebook_id; } public String getCn_user_id() { return cn_user_id; } public void setCn_user_id(String cn_user_id) { this.cn_user_id = cn_user_id; } public String getCn_notebook_type_id() { return cn_notebook_type_id; } public void setCn_notebook_type_id(String cn_notebook_type_id) { this.cn_notebook_type_id = cn_notebook_type_id; } public String getCn_notebook_name() { return cn_notebook_name; } public void setCn_notebook_name(String cn_notebook_name) { this.cn_notebook_name = cn_notebook_name; } public String getCn_notebook_desc() { return cn_notebook_desc; } public void setCn_notebook_desc(String cn_notebook_desc) { this.cn_notebook_desc = cn_notebook_desc; } public Timestamp getCn_notebook_createtime() { return cn_notebook_createtime; } public void setCn_notebook_createtime(Timestamp cn_notebook_createtime) { this.cn_notebook_createtime = cn_notebook_createtime; } @Override public String toString() { return "Book [cn_notebook_id=" + cn_notebook_id + ", cn_user_id=" + cn_user_id + ", cn_notebook_type_id=" + cn_notebook_type_id + ", cn_notebook_name=" + cn_notebook_name + ", cn_notebook_desc=" + cn_notebook_desc + ", cn_notebook_createtime=" + cn_notebook_createtime + ", user=" + user + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((cn_notebook_createtime == null) ? 0 : cn_notebook_createtime.hashCode()); result = prime * result + ((cn_notebook_desc == null) ? 0 : cn_notebook_desc.hashCode()); result = prime * result + ((cn_notebook_id == null) ? 0 : cn_notebook_id.hashCode()); result = prime * result + ((cn_notebook_name == null) ? 0 : cn_notebook_name.hashCode()); result = prime * result + ((cn_notebook_type_id == null) ? 0 : cn_notebook_type_id.hashCode()); result = prime * result + ((cn_user_id == null) ? 0 : cn_user_id.hashCode()); result = prime * result + ((user == null) ? 0 : user.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Book other = (Book) obj; if (cn_notebook_createtime == null) { if (other.cn_notebook_createtime != null) return false; } else if (!cn_notebook_createtime.equals(other.cn_notebook_createtime)) return false; if (cn_notebook_desc == null) { if (other.cn_notebook_desc != null) return false; } else if (!cn_notebook_desc.equals(other.cn_notebook_desc)) return false; if (cn_notebook_id == null) { if (other.cn_notebook_id != null) return false; } else if (!cn_notebook_id.equals(other.cn_notebook_id)) return false; if (cn_notebook_name == null) { if (other.cn_notebook_name != null) return false; } else if (!cn_notebook_name.equals(other.cn_notebook_name)) return false; if (cn_notebook_type_id == null) { if (other.cn_notebook_type_id != null) return false; } else if (!cn_notebook_type_id.equals(other.cn_notebook_type_id)) return false; if (cn_user_id == null) { if (other.cn_user_id != null) return false; } else if (!cn_user_id.equals(other.cn_user_id)) return false; if (user == null) { if (other.user != null) return false; } else if (!user.equals(other.user)) return false; return true; } }
package com.stevezong.cloud_note.dao; import java.util.List; import com.stevezong.cloud_note.entity.Book; import com.stevezong.cloud_note.entity.User; public interface RelationDao { public User findUserAndBooks(String userId); public User findUserAndBooks1(String userId); public List<Book> findBookAndUser(); }
<!-- 两条语句加载book和关联的User信息 --> <select id="findBookAndUser" resultMap="bookMap"> SELECT * FROM cn_notebook </select> <resultMap id="bookMap" type="com.stevezong.cloud_note.entity.Book"> <association property="user" javaType="com.stevezong.cloud_note.entity.User" select="findUser" column="cn_user_id"></association> </resultMap> <select id="findUser" resultType="com.stevezong.cloud_note.entity.User" parameterType="String"> SELECT * FROM cn_user WHERE cn_user_id=#{id} </select> <!-- 一条语句加载book和关联的User信息 --> <select id="findBookAndUser1" resultMap="bookMap1"> SELECT * FROM cn_notebook nb JOIN cn_user u ON (nb.cn_user_id=u.cn_user_id) </select> <resultMap id="bookMap1" type="com.stevezong.cloud_note.entity.Book"> <id property="cn_notebook_id" column="cn_notebook_id"/> <result property="cn_user_id" column="cn_user_id"/> <result property="cn_notebook_type_id" column="cn_notebook_type_id"/> <result property="cn_notebook_name" column="cn_notebook_name"/> <result property="cn_notebook_desc" column="cn_notebook_desc"/> <result property="cn_notebook_createtime" column="cn_notebook_createtime"/> <collection property="user" javaType="com.stevezong.cloud_note.entity.User"> <id property="cn_user_id" column="cn_user_id"/> <result property="cn_user_name" column="cn_user_name"/> <result property="cn_user_password" column="cn_user_password"/> <result property="cn_user_token" column="cn_user_token"/> <result property="cn_user_nick" column="cn_user_nick"/> </collection> </resultMap>
@Test public void t2() { List<Book> books = dao.findBookAndUser(); for(Book sub:books) { System.out.println(sub.getUser()); } }
在开发中碰到用户注册的功能需要用到用户ID,但是用户ID是数据库自增生成的,这种情况上网查询后使用下面的方式配置mybatis的insert语句可以解决:
在库即可使用子层或者序列作为主键值是如何在insert执行后 立刻获取ID值
<insert id="insert" keyProperty="id" useGeneratedKeys="true" parameterType="com.demo.domain.User"> insert into User_t(name,age,addr) values(#{name},#{age},#{addr}) </insert>
@Override public int insert(User user) { int insertNum = Integer.parseInt(userMapper.insert(user) + ""); Long id = user.getId();//该对象的自增ID return insertNum; }
动态SQL
if
choose
trim
foreach
when
<update id="updateNoteByMap" parameterType="map"> UPDATE cn_note SET <trim suffixOverrides=","> <if test="title != null"> cn_note_title=#{title}, </if> <if test="body != null"> cn_note_body=#{body}, </if> <choose> <when test="time != null"> cn_note_last_modify_time=#{time} </when> <otherwise> cn_note_last_modify_time=UNIX_TIMESTAMP() </otherwise> </choose> </trim> WHERE cn_note_id=#{noteId} </update>
<delete id="deleteNotes" parameterType="map"> DELETE FROM cn_note WHERE <if test="status != null"> cn_note_status_id=#{status} AND </if> cn_note_id IN <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach> </delete>
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
#{} 占位符
SELECT
*
FROM
emp
WHERE
name=#{name}
SELECT * FROM emp WHERE name =‘张三‘
${} 字符串拼接
SELECT
*
FROM
emp
WHERE
name LIKE ‘%${name}%‘
SELECT * FROM emp WHERE name LIKE ‘%张三%‘
在使用#{} 的时候 里面可以随便写 #{v},#{value},#{hhhg},#{asdf},#{bbb},#{aaaa},#{name}
在使用${} 的事件 里面只能用 value => ${value}
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中
selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查询一条或多条记录。
mysql自增主键返回
查询id的sql
SELECT LAST_INSERT_ID()
通过修改User.xml映射文件,可以将mysql自增主键返回:
如下添加selectKey 标签
<!-- 保存用户 --> <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User"> <!-- selectKey 标签实现主键返回 --> <!-- keyColumn:主键对应的表中的哪一列 --> <!-- keyProperty:主键对应的pojo中的哪一个属性 --> <!-- order:设置在执行insert语句前执行查询id的sql,孩纸在执行insert语句之后执行查询id的sql --> <!-- resultType:设置返回的id的类型 --> <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO `user` (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address}) </insert>
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
在java代码中 直接 user.getId();就可以获取到Id的值了
Mysql使用 uuid实现主键
需要增加通过select uuid()得到uuid值
<!-- 保存用户 --> <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User"> <!-- selectKey 标签实现主键返回 --> <!-- keyColumn:主键对应的表中的哪一列 --> <!-- keyProperty:主键对应的pojo中的哪一个属性 --> <!-- order:设置在执行insert语句前执行查询id的sql,在执行insert语句之后执行查询id的sql --> <!-- resultType:设置返回的id的类型 --> <selectKey keyColumn="id" keyProperty="id" order="BEFORE" resultType="string"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO `user` (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address}) </insert>
注意这里使用的order是“BEFORE”
在java代码中 直接 user.getId();就可以获取到Id的值了
mybatis与hibernate不同
Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。
SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
<!-- 根据条件查询用户 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE 1=1 <if test="sex != null and sex != ‘‘"> AND sex = #{sex} </if> <if test="username != null and username != ‘‘"> AND username LIKE ‘%${username}%‘ </if> </select>
升级
<!-- 根据条件查询用户 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` <!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 --> <where> <if test="sex != null"> AND sex = #{sex} </if> <if test="username != null and username != ‘‘"> AND username LIKE ‘%${username}%‘ </if> </where> </select>
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
再次升级
片段,如下:
<!-- 根据条件查询用户 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> <!-- SELECT id, username, birthday, sex, address FROM `user` --> <!-- 使用include标签加载sql片段;refid是sql片段id --> SELECT <include refid="userFields" /> FROM `user` <!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 --> <where> <if test="sex != null"> AND sex = #{sex} </if> <if test="username != null and username != ‘‘"> AND username LIKE ‘%${username}%‘ </if> </where> </select> <!-- 声明sql片段 --> <sql id="userFields"> id, username, birthday, sex, address </sql>
<!-- 根据ids查询用户 --> <select id="queryUserByIds" parameterType="queryVo" resultType="user"> SELECT * FROM `user` <where> <!-- foreach标签,进行遍历 --> <!-- collection:遍历的集合,这里是QueryVo的ids属性 --> <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 --> <!-- open:在前面添加的sql片段 --> <!-- close:在结尾处添加的sql片段 --> <!-- separator:指定遍历的元素之间使用的分隔符 --> <foreach collection="ids" item="item" open="id IN (" close=")" separator=","> #{item} </foreach> </where> </select>
在 多个id 使用 int[] ids = new int[] {1,2,3};
collection 的值就必须要用array 规定
<select id="queryUserByIds" parameterType="queryVo" resultType="user"> SELECT * FROM `user` <where> <!-- foreach标签,进行遍历 --> <!-- collection:遍历的集合,这里是QueryVo的ids属性 --> <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 --> <!-- open:在前面添加的sql片段 --> <!-- close:在结尾处添加的sql片段 --> <!-- separator:指定遍历的元素之间使用的分隔符 --> <foreach collection="array" item="item" open="id IN (" close=")" separator=","> #{item} </foreach> </where> </select>
在使用 list的时候 值就是用 list
mybatis 自带的查询条件
TbItemExample example = new TbItemExample();//逆向工程生成的
Criteria criteria = example.createCriteria();
标签:factor use ids instance save sfb sep 基本类型 cas
原文地址:https://www.cnblogs.com/lmdtx/p/9765516.html