[toc]html
文章内容图片部分上传失败,欢迎阅读,白嫖电子书。
声明:参考来源互联网,有任何争议能够留言。站在前人的肩上,咱们才能看的更远。本教程纯手打,致力于最实用教程,不须要什么奖励,只但愿多多转发支持。
欢迎来我公众号,但愿能够结识你,也能够催更,微信搜索:JavaPubjava有任何问题均可以来谈谈,等你哦!mysql
对mybatis有必定了解的,能够直接跳过前面基础引入部分。
![idea建立maven工程截图]()
![idea建立maven工程截图]()面试
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency>
create database mydatabase;
DROP TABLE IF EXISTS tb_user; CREATE TABLE tb_user ( id char(32) NOT NULL, user_name varchar(32) DEFAULT NULL, password varchar(32) DEFAULT NULL, name varchar(32) DEFAULT NULL, age int(10) DEFAULT NULL, sex int(2) DEFAULT NULL, birthday date DEFAULT NULL, created datetime DEFAULT NULL, updated datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO mydatabase.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘zpc’, ‘123456’, ‘小明’, ‘22’, ‘1’, ‘1990-09-02’, sysdate(), sysdate()); INSERT INTO mydatabase.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘hj’, ‘123456’, ‘静静’, ‘22’, ‘1’, ‘1993-09-05’, sysdate(), sysdate());
7步操做数据库spring
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; /** * @author Evan */ public class JDBCTest { public static void main(String[] args) throws Exception { Connection connection = null; PreparedStatement prepareStatement = null; ResultSet rs = null; try { // 1,加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 2,获取链接 String url = "jdbc:mysql://127.0.0.1:3306/mydatabase"; String user = "root"; String password = "123456"; connection = DriverManager.getConnection(url, user, password); // 3,获取statement,preparedStatement String sql = "select * from tb_user where id=?"; prepareStatement = connection.prepareStatement(sql); // 4,设置参数 prepareStatement.setLong(1, 1l); // 5,执行查询 rs = prepareStatement.executeQuery(); // 6,处理结果集 while (rs.next()) { System.out.println(rs.getString("userName")); System.out.println(rs.getString("name")); System.out.println(rs.getInt("age")); System.out.println(rs.getDate("birthday")); } } finally { // 7,关闭链接,释放资源 if (rs != null) { rs.close(); } if (prepareStatement != null) { prepareStatement.close(); } if (connection != null) { connection.close(); } } } }
![介绍截图]()sql
官方文档 http://www.mybatis.org/mybati...
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency>
<?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>--> <!-- <property name="driver" value="com.mysql.jdbc.Driver"/>--> <!-- <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true"/>--> <!-- <property name="username" value="root"/>--> <!-- <property name="password" value="123456"/>--> <!--</properties>--> <!-- 环境,能够配置多个,default:指定采用哪一个环境 --> <environments default="test"> <!-- id:惟一标识 --> <environment id="test"> <!-- 事务管理器,JDBC类型的事务管理器 --> <transactionManager type="JDBC" /> <!-- 数据源,池类型的数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> <environment id="development"> <!-- 事务管理器,JDBC类型的事务管理器 --> <transactionManager type="JDBC" /> <!-- 数据源,池类型的数据源 --> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <!-- 配置了properties,因此能够直接引用 --> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> </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:命名空间,随便写,通常保证命名空间惟一 --> <mapper namespace="MyMapper"> <!-- statement,内容:sql语句。id:惟一标识,随便写,在同一个命名空间下保持惟一 resultType:sql语句查询结果集的封装类型,tb_user即为数据库中的表名 --> <select id="selectUser" resultType="com.zpc.mybatis.User"> select * from tb_user where id = #{id} </select> </mapper>
加入MyMapper.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> <!-- 环境,能够配置多个,default:指定采用哪一个环境 --> <environments default="test"> <!-- id:惟一标识 --> <environment id="test"> <!-- 事务管理器,JDBC类型的事务管理器 --> <transactionManager type="JDBC" /> <!-- 数据源,池类型的数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mydatabase" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <mapper resource="mappers/MyMapper.xml" /> </mappers> </configuration>
// 指定全局配置文件 String resource = "mybatis-config.xml"; // 读取配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); // 构建sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 操做CRUD,第一个参数:指定statement,规则:命名空间+“.”+statementId // 第二个参数:指定传入sql的参数:这里是用户id User user = sqlSession.selectOne("MyMapper.selectUser", 1); System.out.println(user);
MyBatisTest.javaapache
import com.zpc.test.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; public class MybatisTest { public static void main(String[] args) throws Exception { // 指定全局配置文件 String resource = "mybatis-config.xml"; // 读取配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); // 构建sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 获取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); try { // 操做CRUD,第一个参数:指定statement,规则:命名空间+“.”+statementId // 第二个参数:指定传入sql的参数:这里是用户id User user = sqlSession.selectOne("MyMapper.selectUser", 1); System.out.println(user); } finally { sqlSession.close(); } } }
User.java缓存
import java.text.SimpleDateFormat; import java.util.Date; public class User { private String id; private String userName; private String password; private String name; private Integer age; private Integer sex; private Date birthday; private String created; private String updated; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } 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; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getCreated() { return created; } public void setCreated(String created) { this.created = created; } public String getUpdated() { return updated; } public void setUpdated(String updated) { this.updated = updated; } }
1)配置mybatis-config.xml 全局的配置文件 (一、数据源,二、外部的mapper)2)建立SqlSessionFactory微信
3)经过SqlSessionFactory建立SqlSession对象
4)经过SqlSession操做数据库 CRUD
5)调用session.commit()提交事务
6)调用session.close()关闭会话
import com.zpc.mybatis.pojo.User; import java.util.List; public interface UserDao { /** * 根据id查询用户信息 * * @param id * @return */ public User queryUserById(String id); /** * 查询全部用户信息 * * @return */ public List<User> queryUserAll(); /** * 新增用户 * * @param user */ public void insertUser(User user); /** * 更新用户信息 * * @param user */ public void updateUser(User user); /** * 根据id删除用户信息 * * @param id */ public void deleteUser(String id); }
import com.zpc.mybatis.dao.UserDao; import com.zpc.mybatis.pojo.User; import org.apache.ibatis.session.SqlSession; import java.util.List; public class UserDaoImpl implements UserDao { public SqlSession sqlSession; public UserDaoImpl(SqlSession sqlSession) { this.sqlSession = sqlSession; } @Override public User queryUserById(String id) { return this.sqlSession.selectOne("UserDao.queryUserById", id); } @Override public List<User> queryUserAll() { return this.sqlSession.selectList("UserDao.queryUserAll"); } @Override public void insertUser(User user) { this.sqlSession.insert("UserDao.insertUser", user); } @Override public void updateUser(User user) { this.sqlSession.update("UserDao.updateUser", user); } @Override public void deleteUser(String id) { this.sqlSession.delete("UserDao.deleteUser", 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:命名空间,随便写,通常保证命名空间惟一 --> <mapper namespace="UserDao"> <!-- statement,内容:sql语句。id:惟一标识,随便写,在同一个命名空间下保持惟一 resultType:sql语句查询结果集的封装类型,tb_user即为数据库中的表 --> <!--<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">--> <!--select * from tb_user where id = #{id}--> <!--</select>--> <!--使用别名--> <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User"> select tuser.id as id, tuser.user_name as userName, tuser.password as password, tuser.name as name, tuser.age as age, tuser.birthday as birthday, tuser.sex as sex, tuser.created as created, tuser.updated as updated from tb_user tuser where tuser.id = #{id}; </select> <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user; </select> <!--插入数据--> <insert id="insertUser" parameterType="com.zpc.mybatis.pojo.User"> INSERT INTO tb_user ( user_name, password, name, age, sex, birthday, created, updated ) VALUES ( #{userName}, #{password}, #{name}, #{age}, #{sex}, #{birthday}, now(), now() ); </insert> <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User"> UPDATE tb_user <trim prefix="set" suffixOverrides=","> <if test="userName!=null">user_name = #{userName},</if> <if test="password!=null">password = #{password},</if> <if test="name!=null">name = #{name},</if> <if test="age!=null">age = #{age},</if> <if test="sex!=null">sex = #{sex},</if> <if test="birthday!=null">birthday = #{birthday},</if> updated = now(), </trim> WHERE (id = #{id}); </update> <delete id="deleteUser"> delete from tb_user where id=#{id} </delete> </mapper>
<mappers> <mapper resource="mappers/MyMapper.xml"/> <mapper resource="mappers/UserDaoMapper.xml"/> </mappers>
pom.xml文件添加junit依赖
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
UserDao.java,按住Alt+Enter,选择create test
import com.zpc.mybatis.dao.UserDao; import com.zpc.mybatis.dao.impl.UserDaoImpl; import com.zpc.mybatis.pojo.User; import org.apache.ibatis.io.Resources; 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 java.io.InputStream; import java.util.Date; import java.util.List; public class UserDaoTest { public UserDao userDao; public SqlSession sqlSession; @Before public void setUp() throws Exception { // mybatis-config.xml String resource = "mybatis-config.xml"; // 读取配置文件 InputStream is = Resources.getResourceAsStream(resource); // 构建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); // 获取sqlSession sqlSession = sqlSessionFactory.openSession(); this.userDao = new UserDaoImpl(sqlSession); } @Test public void queryUserById() throws Exception { System.out.println(this.userDao.queryUserById("1")); } @Test public void queryUserAll() throws Exception { List<User> userList = this.userDao.queryUserAll(); for (User user : userList) { System.out.println(user); } } @Test public void insertUser() throws Exception { User user = new User(); user.setAge(16); user.setBirthday(new Date("1990/09/02")); user.setName("大鹏"); user.setPassword("123456"); user.setSex(1); user.setUserName("evan"); this.userDao.insertUser(user); this.sqlSession.commit(); } @Test public void updateUser() throws Exception { User user = new User(); user.setBirthday(new Date()); user.setName("静鹏"); user.setPassword("654321"); user.setSex(1); user.setUserName("evanjin"); user.setId("1"); this.userDao.updateUser(user); this.sqlSession.commit(); } @Test public void deleteUser() throws Exception { this.userDao.deleteUser("4"); this.sqlSession.commit(); } }
查询数据的时候,发现查不到userName的信息,
User{id=‘2’, userName=‘null’, password=‘123456’, name=‘静静’, age=22, sex=0, birthday=‘1993-09-05’, created=‘2018-06-30 18:22:28.0’, updated=‘2018-06-30 18:22:28.0’}
缘由:数据库的字段名是user_name,POJO中的属性名字是userName
两端不一致,形成mybatis没法填充对应的字段信息。修改方法:在sql语句中使用别名。
<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User"> select tuser.id as id, tuser.user_name as userName, tuser.password as password, tuser.name as name, tuser.age as age, tuser.birthday as birthday, tuser.sex as sex, tuser.created as created, tuser.updated as updated from tb_user tuser where tuser.id = #{id}; </select>
org.apache.ibatis.binding.BindingException: Type interface com.zpc.mybatis.dao.UserDao is not known to the MapperRegistry. at org.apache.ibatis.binding.MapperRegistry.getMapper(MapperRegistry.java:47) at org.apache.ibatis.session.Configuration.getMapper(Configuration.java:655) at org.apache.ibatis.session.defaults.DefaultSqlSession.getMapper(DefaultSqlSession.java:222) at com.zpc.mybatis.test.UserDaoTest.setUp(UserDaoTest.java:32)
mapper.xml namespace
若是但愿使用mybatis经过的动态代理的接口,就须要namespace中的值,和须要对应的Mapper(dao)接口的全路径一致。Mapper中Namespace的定义自己是没有限制的,只要不重复便可,但若是使用Mybatis的DAO接口动态代理,则namespace必须为DAO接口的全路径,例如:com.zpc.mybatis.dao.UserDao
<mapper namespace="com.zpc.mybatis.dao.UserDao">
public interface UserMapper { /** * 登陆(直接使用注解指定传入参数名称) * @param userName * @param password * @return */ public User login(@Param("userName") String userName, @Param("password") String password); /** * 根据表名查询用户信息(直接使用注解指定传入参数名称) * @param tableName * @return */ public List<User> queryUserByTableName(@Param("tableName") String tableName); /** * 根据Id查询用户信息 * @param id * @return */ public User queryUserById(Long id); /** * 查询全部用户信息 * @return */ public List<User> queryUserAll(); /** * 新增用户信息 * @param user */ public void insertUser(User user); /** * 根据id更新用户信息 * @param user */ public void updateUser(User user); /** * 根据id删除用户信息 * @param id */ public void deleteUserById(Long 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:命名空间,随便写,通常保证命名空间惟一 ,为了使用接口动态代理,这里必须是接口的全路径名--> <mapper namespace="com.zpc.mybatis.dao.UserMapper"> <!-- 1.#{},预编译的方式preparedstatement,使用占位符替换,防止sql注入,一个参数的时候,任意参数名能够接收 2.${},普通的Statement,字符串直接拼接,不能够防止sql注入,一个参数的时候,必须使用${value}接收参数 --> <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from ${tableName} </select> <select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{userName} and password = #{password} </select> <!-- statement,内容:sql语句。 id:惟一标识,随便写,在同一个命名空间下保持惟一,使用动态代理以后要求和方法名保持一致 resultType:sql语句查询结果集的封装类型,使用动态代理以后和方法的返回类型一致;resultMap:二选一 parameterType:参数的类型,使用动态代理以后和方法的参数类型一致 --> <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where id = #{id} </select> <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user </select> <!-- 新增的Statement id:惟一标识,随便写,在同一个命名空间下保持惟一,使用动态代理以后要求和方法名保持一致 parameterType:参数的类型,使用动态代理以后和方法的参数类型一致 useGeneratedKeys:开启主键回写 keyColumn:指定数据库的主键 keyProperty:主键对应的pojo属性名 --> <insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id" parameterType="com.zpc.mybatis.pojo.User"> INSERT INTO tb_user ( id, user_name, password, name, age, sex, birthday, created, updated ) VALUES ( null, #{userName}, #{password}, #{name}, #{age}, #{sex}, #{birthday}, NOW(), NOW() ); </insert> <!-- 更新的statement id:惟一标识,随便写,在同一个命名空间下保持惟一,使用动态代理以后要求和方法名保持一致 parameterType:参数的类型,使用动态代理以后和方法的参数类型一致 --> <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User"> UPDATE tb_user <trim prefix="set" suffixOverrides=","> <if test="userName!=null">user_name = #{userName},</if> <if test="password!=null">password = #{password},</if> <if test="name!=null">name = #{name},</if> <if test="age!=null">age = #{age},</if> <if test="sex!=null">sex = #{sex},</if> <if test="birthday!=null">birthday = #{birthday},</if> updated = now(), </trim> WHERE (id = #{id}); </update> <!-- 删除的statement id:惟一标识,随便写,在同一个命名空间下保持惟一,使用动态代理以后要求和方法名保持一致 parameterType:参数的类型,使用动态代理以后和方法的参数类型一致 --> <delete id="deleteUserById" parameterType="java.lang.String"> delete from tb_user where id=#{id} </delete> </mapper>
<mappers> <mapper resource="mappers/MyMapper.xml"/> <mapper resource="mappers/UserDaoMapper.xml"/> <mapper resource="mappers/UserMapper.xml"/> </mappers>
import com.zpc.mybatis.dao.UserMapper; import com.zpc.mybatis.pojo.User; import org.apache.ibatis.io.Resources; 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 java.io.InputStream; import java.util.Date; import java.util.List; public class UserMapperTest { public UserMapper userMapper; @Before public void setUp() throws Exception { // 指定配置文件 String resource = "mybatis-config.xml"; // 读取配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); // 构建sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 获取sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(true); // 1. 映射文件的命名空间(namespace)必须是mapper接口的全路径 // 2. 映射文件的statement的id必须和mapper接口的方法名保持一致 // 3. Statement的resultType必须和mapper接口方法的返回类型一致 // 4. statement的parameterType必须和mapper接口方法的参数类型一致(不必定) this.userMapper = sqlSession.getMapper(UserMapper.class); } @Test public void testQueryUserByTableName() { List<User> userList = this.userMapper.queryUserByTableName("tb_user"); for (User user : userList) { System.out.println(user); } } @Test public void testLogin() { System.out.println(this.userMapper.login("hj", "123456")); } @Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); } @Test public void testQueryUserAll() { List<User> userList = this.userMapper.queryUserAll(); for (User user : userList) { System.out.println(user); } } @Test public void testInsertUser() { User user = new User(); user.setAge(20); user.setBirthday(new Date()); user.setName("大神"); user.setPassword("123456"); user.setSex(2); user.setUserName("bigGod222"); this.userMapper.insertUser(user); System.out.println(user.getId()); } @Test public void testUpdateUser() { User user = new User(); user.setBirthday(new Date()); user.setName("静静"); user.setPassword("123456"); user.setSex(0); user.setUserName("Jinjin"); user.setId("1"); this.userMapper.updateUser(user); } @Test public void testDeleteUserById() { this.userMapper.deleteUserById("1"); } }
使用mapper接口不用写接口实现类便可完成数据库操做,使用很是方便,也是官方推荐的使用方式。
- Mapper的namespace必须和mapper接口的全路径一致。
- Mapper接口的方法名必须和sql定义的id一致。
- Mapper接口中方法的输入参数类型必须和sql定义的parameterType一致。(这句须要再琢磨)
- Mapper接口中方法的输出参数类型必须和sql定义的resultType一致。
mybatis-config.xml讲究严格的顺序,具体顺序遵循文档的顺序。
properties配置的属性都是可外部配置且可动态替换的,既能够在典型的 Java 属性文件中配置,亦可经过 properties 元素的子元素来传递。例如:
<properties resource="org/mybatis/example/config.properties"> <property name="username" value="dev_user"/> <property name="password" value="F2Fa3!33TYyg"/> </properties>
而后其中的属性就能够在整个配置文件中被用来替换须要动态配置的属性值。好比:
<dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>
这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换。 driver 和 url 属性将会由 config.properties 文件中对应的值来替换。这样就为配置提供了诸多灵活选择。
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props); // ... or ... SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);
若是属性在不仅一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:
- 在 properties 元素体内指定的属性首先被读取。
- 而后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。
- 最后读取做为方法参数传递的属性,并覆盖已读取的同名属性。
所以,经过方法参数传递的属性具备最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
类型别名是为 Java 类型命名的一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减小类彻底限定名的冗余。
<typeAliases> <typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/> </typeAliases>
缺点:每一个pojo类都要去配置。
解决方案:使用扫描包,扫描指定包下的全部类,扫描以后的别名就是类名(不区分大小写),建议使用的时候和类名一致
<typeAliases> <!--type:实体类的全路径。alias:别名,一般首字母大写--> <!--<typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/>--> <package name="com.zpc.mybatis.pojo"/> </typeAliases>
Mybatis已经为普通的 Java 类型内建了许多相应的类型别名。它们都是大小写不敏感的。
不管是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,仍是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。能够重写类型处理器或建立你本身的类型处理器来处理不支持的或非标准的类型。
MyBatis 容许你在已映射语句执行过程当中的某一点进行拦截调用。默认状况下,MyBatis 容许使用插件来拦截的方法调用包括:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
如今一些MyBatis 插件好比PageHelper都是基于这个原理,有时为了监控sql执行效率,也可使用插件机制
原理:
// ExamplePlugin.java @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { } }
配置:
<!-- mybatis-config.xml --> <plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
上面的插件将会拦截在 Executor 实例中全部的 “update” 方法调用, 这里的 Executor 是负责执行低层映射语句的内部对象。
MyBatis 能够配置成适应多种环境,例如,开发、测试和生产环境须要有不一样的配置;
尽管能够配置多个环境,每一个 SqlSessionFactory 实例只能选择其一。
虽然,这种方式也能够作到很方便的分离多个环境,可是实际使用场景下,咱们更多的是选择使用spring来管理数据源,来作到环境的分离。
须要告诉 MyBatis 到哪里去找到 SQL 映射语句。即告诉 MyBatis 到哪里去找映射文件。你可使用相对于类路径的资源引用, 或彻底限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如:
<!-- 使用相对于类路径的资源引用 --> <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers> <!-- 使用映射器接口实现类的彻底限定类名 --> <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
这里所谓的mapper接口路径。实际上就是dao的接口路径。在mybatis中,一般把dao的包叫作mapper。类名,也叫作mapper
- 定义一个接口。
- 在接口所在的包中定义mapper.xml,而且要求xml文件和interface的名称要相同。
- 在mybatis-config.xml 中经过class路径,引入mapper(注解方式)。要求mapper.xml 中的名称空间是类的接口的全路径。
注解方式:
<mappers> <mapper resource="mappers/MyMapper.xml"/> <mapper resource="mappers/UserDaoMapper.xml"/> <!--注解方式可使用以下配置方式--> <mapper class="com.zpc.mybatis.dao.UserMapper"/> </mappers>
问题:
固然也可使用包扫描(必须使用注解方式,即在接口方法上使用注解,如@Select("select * from tb_user ")):
缺点:
select – 书写查询sql语句
select中的几个属性说明:
id属性:当前名称空间下的statement的惟一标识。必须。要求id和mapper接口中的方法的名字一致。
resultType:将结果集映射为java的对象类型。必须(和 resultMap 二选一)
parameterType:传入参数类型。能够省略
insert 的几个属性说明:
id:惟一标识,随便写,在同一个命名空间下保持惟一,使用动态代理以后要求和方法名保持一致
parameterType:参数的类型,使用动态代理以后和方法的参数类型一致
useGeneratedKeys:开启主键回写
keyColumn:指定数据库的主键
keyProperty:主键对应的pojo属性名
标签内部:具体的sql语句。
id属性:当前名称空间下的statement的惟一标识(必须属性);
parameterType:传入的参数类型,能够省略。
标签内部:具体的sql语句。
delete 的几个属性说明:
id属性:当前名称空间下的statement的惟一标识(必须属性);
parameterType:传入的参数类型,能够省略。
标签内部:具体的sql语句。
场景:数据库有两个如出一辙的表。历史表,当前表
查询表中的信息,有时候从历史表中去查询数据,有时候须要去新的表去查询数据。
但愿使用1个方法来完成操做。
<select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from #{tableName} </select> /** * 根据表名查询用户信息(直接使用注解指定传入参数名称) * * @param tableName * @return */ public List<User> queryUserByTableName(String tableName);
测试输出:
有问题,报语法错误:至关于执行了这样一条sql:
select * from “tb_user”;
显然表名多了引号。
<select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from ${tableName} </select>
注意:
${} 是进行字符串拼接,至关于sql语句中的Statement,使用字符串去拼接sql;$能够是sql中的任一部分传入到Statement中,不能防止sql注入。
使用${} 去取出参数值信息,须要使用${value}
推荐:
/** * 根据表名查询用户信息(直接使用注解指定传入参数名称) * * @param tableName * @return */ public List<User> queryUserByTableName(@Param("tableName") String tableName); <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User"> select * from ${tableName} </select>
/** * 登陆(直接使用注解指定传入参数名称) * * @param userName * @param password * @return */ public User login( String userName, String password); <select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{userName} and password = #{password} </select>
报错:
org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2] ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2]
解决方案一:
<select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{0} and password = #{1} </select>
解决方案二:
<select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{param1} and password = #{param2} </select>
最终解决方案:
/** * 登陆(直接使用注解指定传入参数名称) * * @param userName * @param password * @return */ public User login(@Param("userName") String userName, @Param("password") String password); <select id="login" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where user_name = #{userName} and password = #{password} </select>
一般在方法的参数列表上加上一个注释@Param(“xxxx”) 显式指定参数的名字,而后经过${“xxxx”}或#{“xxxx”}
sql语句动态生成的时候,使用${};
sql语句中某个参数进行占位的时候#{}
/** * #号 * @param username1 * @return */ User queryUserListByName1(@Param("username1") String username1); /** * $号 * @param username2 * @return */ User queryUserListByName2(@Param("username2") String username2); <select id="queryUserListByName1" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE user_name=#{username1} </select> <select id="queryUserListByName2" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE user_name='${username2}'//手动加了引号 </select>
使用:
<sql id=””></sql> <include refId=”” />
例如在UserMapper.xml中定义以下片断:
<sql id="commonSql"> id, user_name, password, name, age, sex, birthday, created, updated </sql>
则能够在UserMapper.xml中使用它:
<select id="queryUserById" resultMap="userResultMap"> select <include refid="commonSql"></include> from tb_user where id = #{id} </select> <select id="queryUsersLikeUserName" resultType="User"> select <include refid="commonSql"></include> from tb_user where user_name like "%"#{userName}"%" </select>
Sql片断也能够定义在单独的.xml文件中如:
定义CommonSQL.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="CommonSQL"> <sql id="commonSql"> id, user_name, password, name, age, sex, birthday, created, updated </sql> </mapper>
使用:
<select id="queryUserById" resultMap="userResultMap"> select <include refid="CommonSQL.commonSql"></include> from tb_user where id = #{id} </select> <select id="queryUsersLikeUserName" resultType="User"> select <include refid="CommonSQL.commonSql"></include> from tb_user where user_name like "%"#{userName}"%" </select>
固然要完成这个功能还须要在全局配置文件mybatis-config.xml中引入该外部配置文件:
<mappers> <mapper resource="CommonSQL.xml"/> <!-- 开启mapper接口的包扫描,基于class的配置方式 --> <package name="com.zpc.mybatis.mapper"/> </mappers>
场景:查询男性用户,若是输入了姓名,按姓名模糊查询
场景:查询男性用户,若是输入了姓名,则按姓名查询
定义接口:
/** * 查询男性用户,若是输入了姓名,则按姓名查询 * @param name * @return */ List<User> queryUserList(@Param("name") String name);
编写mapper
<select id="queryUserList" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE sex=1 <if test="name!=null and name.trim()!=''"> and name like '%${name}%' </if> </select>
测试:
@Test public void testqueryUserList() { List<User> users = this.userMapper.queryUserList(null); for (User user : users) { System.out.println(user); } }
场景:查询男性用户,若是输入了姓名则按照姓名模糊查找,不然若是输入了年龄则按照年龄查找,不然查找姓名为“鹏程”的用户。
定义接口:
/** * 查询男性用户,若是输入了姓名则按照姓名模糊查找,不然若是输入了年龄则按照年龄查找,不然查找姓名为“鹏程”的用户。 * @param name * @param age * @return */ List<User> queryUserListByNameOrAge(@Param("name") String name,@Param("age") Integer age);
编写mapper配置:
<select id="queryUserListByNameOrAge" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user WHERE sex=1 <!-- 1.一旦有条件成立的when,后续的when则不会执行 2.当全部的when都不执行时,才会执行otherwise --> <choose> <when test="name!=null and name.trim()!=''"> and name like '%${name}%' </when> <when test="age!=null"> and age = #{age} </when> <otherwise> and name='鹏程' </otherwise> </choose> </select>
测试:
@Test public void queryUserListByNameOrAge() throws Exception { List<User> users = this.userMapper.queryUserListByNameOrAge(null, 16); for (User user : users) { System.out.println(user); } }
场景一:查询全部用户,若是输入了姓名按照姓名进行模糊查询,若是输入年龄,按照年龄进行查询,若是二者都输入,两个条件都要成立。
接口:
/** * 查询全部用户,若是输入了姓名按照姓名进行模糊查询,若是输入年龄,按照年龄进行查询,若是二者都输入,两个条件都要成立 * @param name * @param age * @return */ List<User> queryUserListByNameAndAge(@Param("name") String name,@Param("age") Integer age);
配置:
<select id="queryUserListByNameAndAge" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user <!--若是多出一个and,会自动去除,若是缺乏and或者多出多个and则会报错--> <where> <if test="name!=null and name.trim()!=''"> and name like '%${name}%' </if> <if test="age!=null"> and age = #{age} </if> </where> </select>
测试:
@Test public void queryUserListByNameAndAge() throws Exception { List<User> users = this.userMapper.queryUserListByNameAndAge("鹏程", 20); for (User user : users) { System.out.println(user); } }
场景二:修改用户信息,若是参数user中的某个属性为null,则不修改。
接口:
/** * 根据id更新用户信息 * * @param user */ public void updateUser(User user);
配置:
<update id="updateUser" parameterType="com.zpc.mybatis.pojo.User"> UPDATE tb_user <trim prefix="set" suffixOverrides=","> <if test="userName!=null">user_name = #{userName},</if> <if test="password!=null">password = #{password},</if> <if test="name!=null">name = #{name},</if> <if test="age!=null">age = #{age},</if> <if test="sex!=null">sex = #{sex},</if> <if test="birthday!=null">birthday = #{birthday},</if> updated = now(), </trim> WHERE (id = #{id}); </update>
测试:
@Test public void testUpdateUser() { User user = new User(); user.setBirthday(new Date()); user.setName("静静"); user.setPassword("123456"); user.setSex(0); user.setUserName("Jinjin"); user.setId("1"); this.userMapper.updateUser(user); }
场景:按照多个id查询用户信息
接口:
/** * 按多个Id查询 * @param ids * @return */ List<User> queryUserListByIds(@Param("ids") String[] ids);
配置:
<select id="queryUserListByIds" resultType="com.zpc.mybatis.pojo.User"> select * from tb_user where id in <foreach collection="ids" item="id" open="(" close=")" separator=","> #{id} </foreach> </select>
测试:
@Test public void queryUserListByIds() throws Exception { List<User> users = this.userMapper.queryUserListByIds(new String[]{"1","2"}); for (User user : users) { System.out.println(user); } }
If:testognl表达式或者简单java代码
Choose when otherwise—>至关于if else if else
When test参考if
Where set 都有必定的纠错功能
Trim:prefix suffix prefixOverrides suffixOverrides
Foreach:collection item saparator open close
在mybatis中,一级缓存默认是开启的,而且一直没法关闭
一级缓存知足条件:
一、同一个session中
二、相同的SQL和参数
测试:
@Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); System.out.println(this.userMapper.queryUserById("1")); }
2018-07-01 17:08:50,156 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:08:50,421 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057. 2018-07-01 17:08:50,423 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:08:50,476 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:08:50,509 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鹏程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'} User{id='1', userName='bigGod222', password='123456', name='鹏程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
使用:sqlSession.clearCache();能够强制清除缓存
测试:
@Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); sqlSession.clearCache(); System.out.println(this.userMapper.queryUserById("1")); }
日志:
2018-07-01 17:10:51,065 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:10:51,359 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057. 2018-07-01 17:10:51,360 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:10:51,408 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:10:51,437 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鹏程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'} 2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:10:51,440 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鹏程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
执行update、insert、delete的时候,会清空缓存
测试:
@Test public void testQueryUserById() { System.out.println(this.userMapper.queryUserById("1")); //sqlSession.clearCache(); User user=new User(); user.setName("美女"); user.setId("1"); userMapper.updateUser(user); System.out.println(this.userMapper.queryUserById("1")); }
日志:
2018-07-01 17:18:15,128 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:18:15,399 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057. 2018-07-01 17:18:15,401 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:18:15,466 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:18:15,492 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='鹏程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'} 2018-07-01 17:18:15,527 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==> Preparing: UPDATE tb_user set name = ?, updated = now() WHERE (id = ?); 2018-07-01 17:18:15,529 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==> Parameters: 美女(String), 1(String) 2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] <== Updates: 1 2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:18:15,533 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:18:15,538 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
mybatis 的二级缓存的做用域是一个mapper的namespace ,同一个namespace中查询sql能够从缓存中命中。
开启二级缓存:
<mapper namespace="com.zpc.mybatis.dao.UserMapper"> <cache/> </mapper>
测试:
@Test public void testCache() { System.out.println(this.userMapper.queryUserById("1")); sqlSession.close(); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); System.out.println(mapper.queryUserById("1")); }
开启二级缓存,必须序列化:
public class User implements Serializable{ private static final long serialVersionUID = -3330851033429007657L;
日志:
2018-07-01 17:23:39,335 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection 2018-07-01 17:23:39,664 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 2092769598. 2018-07-01 17:23:39,665 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Preparing: select * from tb_user where id = ? 2018-07-01 17:23:39,712 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String) 2018-07-01 17:23:39,734 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <== Total: 1 User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'} 2018-07-01 17:23:39,743 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cbd213e] 2018-07-01 17:23:39,744 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 2092769598 to pool. 2018-07-01 17:23:39,746 [main] [com.zpc.mybatis.dao.UserMapper]-[DEBUG] Cache Hit Ratio [com.zpc.mybatis.dao.UserMapper]: 0.5 User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
关闭二级缓存:
不开启,或者在全局的mybatis-config.xml 中去关闭二级缓存
<settings> <!--开启驼峰匹配--> <setting name="mapUnderscoreToCamelCase" value="true"/> <!--开启二级缓存,全局总开关,这里关闭,mapper中开启了也没用--> <setting name="cacheEnabled" value="false"/> </settings>
建立order表:
CREATE TABLE tb_order (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) DEFAULT NULL,
order_number varchar(255) DEFAULT NULL,
create datetime DEFAULT NULL,
updated datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
public class Order { private Integer id; private Long userId; private String orderNumber; private Date created; private Date updated; }
需求说明:
方法一:核心思想扩展Order对象,来完成映射
新建OrderUser实体类继承Order:
public class OrderUser extends Order { private String userName; private String password; private String name; private Integer age; private Integer sex; private Date birthday; private Date created; private Date updated; }
OrderMapper接口:
public interface OrderMapper { OrderUser queryOrderUserByOrderNumber(@Param("number") String number); }
配置OrderMapper:
<mapper namespace="com.zpc.mybatis.dao.OrderMapper"> <select id="queryOrderUserByOrderNumber" resultType="com.zpc.mybatis.pojo.OrderUser"> select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number} </select> </mapper>
测试:
@Test public void queryOrderUserByOrderNumber() throws Exception { OrderUser orderUser = orderMapper.queryOrderUserByOrderNumber("201807010001"); System.out.println(orderUser); }
方法二:面向对象的思想,在Order对象中添加User对象。
在Order对象中添加User属性:
public class Order { private Integer id; private Long userId; private String orderNumber; private Date created; private Date updated; private User user; }
接口:
/** * 根据订单号查询订单用户的信息 * @param number * @return */ Order queryOrderWithUserByOrderNumber(@Param("number") String number);
使用resultType不能完成自动映射,须要手动完成结果集映射resultMap:
<resultMap id="OrderUserResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true"> <id column="id" property="id"/> <!--association:完成子对象的映射--> <!--property:子对象在父对象中的属性名--> <!--javaType:子对象的java类型--> <!--autoMapping:完成子对象的自动映射,若开启驼峰,则按驼峰匹配--> <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true"> <id column="user_id" property="id"/> </association> </resultMap> <select id="queryOrderWithUserByOrderNumber" resultMap="OrderUserResultMap"> select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number} </select>
测试:
@Test public void queryOrderWithUserByOrderNumber() throws Exception { Order order = orderMapper.queryOrderWithUserByOrderNumber("201807010001"); System.out.println(order.getUser()); }
一对多查询:查询订单,查询出下单人信息而且查询出订单详情。
Order类:
public class Order { private Integer id; private Long userId; private String orderNumber; private Date created; private Date updated; private User user; private List<OrderDetail> detailList; }
public class OrderDetail { private Integer id; private Integer orderId; private Double totalPrice; private Integer status; }
接口:
/** * 根据订单号查询订单用户的信息及订单详情 * @param number * @return */ Order queryOrderWithUserAndDetailByOrderNumber(@Param("number") String number);
Mapper映射:
<resultMap id="OrderUserDetailResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true"> <id column="id" property="id"/> <!--collection:定义子对象集合映射--> <!--association:完成子对象的映射--> <!--property:子对象在父对象中的属性名--> <!--javaType:子对象的java类型--> <!--autoMapping:完成子对象的自动映射,若开启驼峰,则按驼峰匹配--> <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true"> <id column="user_id" property="id"/> </association> <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true"> <id column="id" property="id"/> </collection> </resultMap> <select id="queryOrderWithUserAndDetailByOrderNumber" resultMap="OrderUserDetailResultMap"> select * from tb_order o left join tb_user u on o.user_id=u.id left join tb_orderdetail od on o.id=od.order_id where o.order_number = #{number} </select>
测试:
@Test public void queryOrderWithUserAndDetailByOrderNumber() throws Exception { Order order = orderMapper.queryOrderWithUserAndDetailByOrderNumber("201807010001"); System.out.println(order.getUser()); System.out.println(order.getDetailList()); }
多对多查询:查询订单,查询出下单人信息而且查询出订单详情中的商品数据。
OrderDetail类
public class OrderDetail { private Integer id; private Integer orderId; private Double totalPrice; private Integer status; private Item item; } public class Item { private Integer id; private String itemName; private Float itemPrice; private String itemDetail; }
接口:
/** * 根据订单号查询订单用户的信息及订单详情及订单详情对应的商品信息 * @param number * @return */ Order queryOrderWithUserAndDetailItemByOrderNumber(@Param("number") String number);
Mapper配置:
<resultMap id="OrderUserDetailItemResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true"> <id column="id" property="id"/> <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true"> <id column="user_id" property="id"/> </association> <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true"> <id column="detail_id" property="id"/> <association property="item" javaType="com.zpc.mybatis.pojo.Item" autoMapping="true"> <id column="item_id" property="id"/> </association> </collection> </resultMap> <select id="queryOrderWithUserAndDetailItemByOrderNumber" resultMap="OrderUserDetailItemResultMap"> select * ,od.id as detail_id from tb_order o left join tb_user u on o.user_id=u.id left join tb_orderdetail od on o.id=od.order_id left join tb_item i on od.item_id=i.id where o.order_number = #{number} </select>
测试:
@Test public void queryOrderWithUserAndDetailItemByOrderNumber() throws Exception { Order order = orderMapper.queryOrderWithUserAndDetailItemByOrderNumber("201807010001"); System.out.println(order); System.out.println(order.getUser()); System.out.println(order.getDetailList()); }
至此,目录结构以下:
数据库脚本: CREATE TABLE tb_order ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) DEFAULT NULL, order_number varchar(255) DEFAULT NULL, create datetime DEFAULT NULL, updated datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO tb_order VALUES (‘1’, ‘2’, ‘201807010001’, ‘2018-07-01 19:38:35’, ‘2018-07-01 19:38:40’); CREATE TABLE tb_item ( id int(11) NOT NULL, itemName varchar(255) DEFAULT NULL, itemPrice decimal(10,2) DEFAULT NULL, itemDetail varchar(255) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO tb_item VALUES (‘1’, ‘袜子’, ‘29.90’, ‘香香的袜子’); INSERT INTO tb_item VALUES (‘2’, ‘套子’, ‘99.99’, ‘冈本001’); CREATE TABLE tb_orderdetail ( id int(11) NOT NULL AUTO_INCREMENT, order_id int(11) DEFAULT NULL, total_price decimal(10,0) DEFAULT NULL, item_id int(11) DEFAULT NULL, status int(10) unsigned zerofill DEFAULT NULL COMMENT ‘0成功非0失败’, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; INSERT INTO tb_orderdetail VALUES (‘1’, ‘1’, ‘10000’, ‘1’, ‘0000000001’); INSERT INTO tb_orderdetail VALUES (‘2’, ‘1’, ‘2000’, ‘2’, ‘0000000000’);
resutlType没法帮助咱们自动的去完成映射,因此只有使用resultMap手动的进行映射。
type 结果集对应的数据类型 id 惟一标识,被引用的时候,进行指定。
<resultMap type="Order" id="orderUserLazyResultMap"> <!—定义pojo中的单个对象的 property 定义对象的属性名, javaType 属性的类型, <association property="user" javaType="User" autoMapping="true"> <id /> </association> <!—若是属性是集合使用collection ,javaType 集合的类型,ofType 表示集中的存储的元素类型 <collection property="details" javaType="List" ofType="OrderDetail" autoMapping="true"> <id /> </resultMap>
后续补充
由于业务,须要在mybatis中,使用到大于号,小于号,因此就在SQL中直接使用了。
但是,在执行时,总报错误:`Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 74; columnNumber: 17;
元素内容必须由格式正确的字符数据或标记组成。
把AND start_date >= CURRENT_DATE AND end_date <= CURRENT_DATE去掉,就没有问题,因此肯定是由于大于号,小于号引发的问题。
因而就想到了特殊符号,因而用了转义字符把>和<替换掉,而后就没有问题了。
案例:
1.<if test="startDateTime!=null"> and mm.ttime > to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss')</if> 2.<if test="endDateTime!=null"> and mm.ttime <= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss')</if>
案例1:
<![CDATA[ and mm.ttime > to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss') and mm.ttime <= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss') ]]>
案例2:
mapper文件示例代码 :
and (t1.status <![CDATA[ >= ]]> 1 and t1.status <![CDATA[ <= ]]> 2) 上述代码其实对应的sql: and (t1.status > =1 andt1.status <= 2)
注意:
使用<![CDATA[ ]]>标记的sql语句中的<where> <if>等标签不会被解析。CDATA 部分中的全部内容都会被解析器忽略。CDATA 部分由 "<![CDATA[" 开始,由 "]]>" 结束