Mybatis和Spring整合&逆向工程
Mybatis和Spring整合
- mybatis整合Spring的思路
- 目的就是将在SqlMapConfig.xml中的配置移植到Spring的applicationContext.xml文件中
- 让spring管理SqlSessionFactory
- 让spring管理mapper对象和dao。
- 使用spring和mybatis整合开发mapper代理及原始dao接口。
- 自动开启事务,自动关闭 sqlsession.
- 让spring管理数据源( 数据库连接池)
- 导入相关的jar包
- 配置配置文件
- log4j.properties
- SqlMapconfig.xml
- applicationContext.xml
整合开发原始dao接口
-
在 applicationContext.xml配置SqlSessionFactory和数据源(DBCP连接池)
<context:property-placeholder location="classpath:jdbc.properties" /> <!-- 数据库连接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" > <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 最大连接数 --> <property name="maxActive" value="20" /> <!-- 最大等待时间 --> <property name="maxWait" value="8000" /> <!-- 最大空闲数 --> <property name="maxIdle" value="3" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 加载数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 加载Mybatis的核心配置文件 --> <property name="configLocation" value="classpath:SqlMapConfig.xml" /> <!-- 别名包扫描 --> <property name="typeAliasesPackage" value="com.syj.mybatis.pojo"/> </bean>
-
开发Dao接口
public interface UserDao { // 根据id查询用户的信息 public User findUserById(int id) throws Exception; // 根据姓名进行模糊查询 public List<User> findUserByName(String username) throws Exception; }
-
Dao实现类
//通常情况下我们回去继承自SqlSessionDaoSupport就可以直接在Spring的配置中直接注入sqlSessionFactory public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao { @Override public User findUserById(int id) throws Exception { SqlSession sqlSession = this.getSqlSession(); User user = sqlSession.selectOne("user.findUserById", id); return user; } @Override public List<User> findUserByName(String username) throws Exception { SqlSession sqlSession = this.getSqlSession(); List<User> list = sqlSession.selectList("user.findUserByName", username); return list; } }
-
在Spring中配置Dao
<!-- 传统Dao配置 --> <bean id="userDao" class="com.syj.mybatis.dao.impl.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
-
测试
public class UserDaoTest { private ApplicationContext applicationContext; @Before public void init() { applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void testFindUserById() throws Exception { UserDao userDao = applicationContext.getBean(UserDao.class); User user = userDao.findUserById(32); System.out.println(user); } @Test public void testFindUserByName() throws Exception { UserDao userDao = (UserDao) applicationContext.getBean("userDao"); List<User> list = userDao.findUserByName("张"); for (User user : list) { System.out.println(user); } } }
整合开发mapper代理的方法
-
编写mapper接口
public interface UserMapper { // 根据id查询用户的信息 public User findUserById(int id) throws Exception; // 根据姓名进行模糊查询 public List<User> findUserByName(String username) throws Exception; // 插入用户 public void insertUser(User user) throws Exception; }
-
编写mapper.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.syj.mybatis.mapper.UserMapper"> <!-- 根据id查询用户信息 --> <select id="findUserById" parameterType="int" resultType="user"> SELECT * FROM USER WHERE id = #{id}; </select> <!-- 根据名字模糊查询用户的信息 --> <select id="findUserByName" resultType="user" parameterType="string"> SELECT * FROM USER WHERE username like '%${value}%'; </select> <!-- 保存用户信息 --> <insert id="insertUser" parameterType="user"> <selectKey keyProperty="id" order="AFTER" resultType="int"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO USER (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address}) </insert> </mapper>
-
在Spring的配置文件中配置mapper.xml文件的映射
<!-- mapper代理Dao开发,第一种方式 -MapperFactoryBean --> <!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean" > <!-- mapperInterface的mapper接口 --> <property name="mapperInterface" value="com.syj.mybatis.mapper.UserMapper" /> <!-- MapperFactoryBean继承自SqlSessionDaoSupport --> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> --> <!-- mapper动态代理Dao开发,第二种方式,包扫描器(推荐使用) MapperScannerConfigurer:mapper的扫描器,将包下面的mapper接口自动创建代理对象 自动创建到Spring容器中,bean的id就是mapper的类名(首字母小写) --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 配置扫描包的路径,如果要扫描多个包,中间使用半角 , 号隔开 --> <property name="basePackage" value="com.syj.mybatis.mapper"/> <!-- 不使用sqlSessionFactory的原因就是和上面的 <context:property-placeholder location="classpath:jdbc.properties" /> 有 冲突 --> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean>
-
测试
逆向工程
什么是逆向工程
-
mybatis需要程序员自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码(mapper.java、mapper.xml、pojo…),可以让程序员将更多的精力放在繁杂的业务逻辑上。
企业实际开发中,常用的逆向工程方式:由数据库的表 —> java代码。
之所以强调单表两个字,是因为Mybatis逆向工程生成的Mapper所进行的操作都是针对单表的,在大型项目中,很少有复杂的多表关联查询,所以作用还是很大的。
-
下载逆向工程:
-
逆向工程的使用
如何运行逆向工程
官网:http://www.mybatis.org/generator/index.html
-
我们使用Java工程生成逆向工程
使用逆向工程生成代码
-
java工程结构
-
GeneratorSqlmap.java
package com.syj.mybatis; import java.io.File; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; public class GeneratorSqlmap { public void generator() throws Exception { List<String> warnings = new ArrayList<String>(); boolean overwrite = true; // 指定逆向工程的配置文件位置 File configFile = new File("./config/generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap(); generatorSqlmap.generator(); } catch (Exception e) { e.printStackTrace(); } } }
-
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis168" userId="root" password="root"> </jdbcConnection> <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" userId="yycg" password="yycg"> </jdbcConnection> --> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成PO类的位置 --> <javaModelGenerator targetPackage="com.syj.mybatis.po" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.syj.mybatis.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.syj.mybatis.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定数据库表 --> <table tableName="items"></table> <table tableName="orders"></table> <table tableName="orderdetail"></table> <table tableName="user"></table> <!-- <table schema="" tableName="sys_user"></table> <table schema="" tableName="sys_role"></table> <table schema="" tableName="sys_permission"></table> <table schema="" tableName="sys_user_role"></table> <table schema="" tableName="sys_role_permission"></table> --> <!-- 有些表的字段需要指定java类型 <table schema="" tableName=""> <columnOverride column="" javaType="" /> </table> --> </context> </generatorConfiguration>
-
配置文件需要修改的内容:
-
数据库驱动、地址、用户名、密码
-
POJO类、mapper接口、mapper映射文件生成的位置
-
指定数据表
-
配置完成之后运行GeneratorSqlmap.java中的main方法就会生成对应数据表的代码,生成后记得右键项目名刷新。如果需要再次生成,一定要记得先把原来生成的删除。
-
生成的代码结构目录
-
我们可以将生成的代码拷贝到工程中进行测试
逆向工程提供的方法
-
查询
方法 作用 selectByExample(TbItemDescExample example)** 通过特定限制条件查询信息,example用于生成一个Criteria对象来设置查询条件 selectByPrimaryKey(Long itemId)** 通过主键查询 selectByExampleWithBLOBs(TbItemDescExample example) 根据特定限制条件查询,返回值包含类型为text的列(默认查询并不会返回该列的信息)。example用于生成一个Criteria对象来设置查询条件,具体使用方法和方法1是一样的,唯一的把不同就是返回值是所有列。 不能指定查询的列,只能够查询所有列。
- selectByExample(TbItemDescExample example)
example用于生成一个Criteria对象来设置查询条件
Criteria对象设置条件逆向工程会根据指定的表去生成多中方法@Test public void testSelectByExample() { // 生成表Example对象 UserExample example = new UserExample(); // 生成criteria对象用于设置查询条件 Criteria criteria = example.createCriteria(); criteria.andIdIn(Arrays.asList(1, 16, 26)); // 1、查询出符合条件的指定信息 // List<User> list = userMapper.selectByExample(example); // for (User user : list) { // System.out.println(user); // } // 2、查询总数 int countByExample = userMapper.countByExample(example); System.out.println(countByExample); }
- selectByPrimaryKey(Long itemId) 、
通过主键查询 - selectByExampleWithBLOBs(TbItemDescExample example)
根据特定限制条件查询,查询大文本
- selectByExample(TbItemDescExample example)
-
保存
相同点: 方法传入的参数都是POJO,返回值都是int类型的受影响的行数。
insert: 插入所有的信息,如果传入的对象某一属性为空,则插入空,如果数据库中设置了默认值,默认值就失效了
insertSelective: 他只会插入含有数据的属性,对于为空的属性,不予以处理,这样的话如果数据库中设置有默认值,就不会被空值覆盖了。
-
更新
第一类:根据特定限制条件进行更新
参数1:Pojo名 record -> 要更新的对象
参数2:Pojo名+Example example -> 生成一个Criteria对象来设置查询条件方法 作用 updateByExample(User record, UserExample example) 根据特定的限制条件进行更新除了text类型(数据库)的所有列。 updateByExampleSelective(Userrecord, UserExample example) 根据特定的限制条件更新所有设置了值的列。 第二类:根据ID进行更新
参数:Pojo名 record -> 要更新的对象方法 作用 updateByPrimaryKey(User record) 通过ID更新除了text类型(数据库)的所有列 updateByPrimaryKeySelective(User record) 通过ID更新所有设置了值的列。 -
删除
方法1:根据特定限制条件删除,具体使用的方法和查询的时候是一样的。
方法2:根据主键删除。
参考:https://blog.csdn.net/qq_39056805/article/details/80585941