spring和mybatis泛型接口的整合(一)
程序员文章站
2024-01-24 11:27:04
...
1、这次使用spring和mybatis进行整合,使用spring的注解和自动扫描的方式将mybatis装载到程序中去。
2、首先看整个的工程包的截图
3、先来分析spring.mybatis.orm包下的类
1)、SqlMapl类属于数据库标识接口,用于spring中的配置使用。
2)、BaseSqlMap类,操作数据库的通用方法接口
3)、BaseEntity类,通用的实体类定义一些通用的属性
4)、MyBatisDao类,通用方法的实现类
5)、ReflectHelper类,工具类,通过java反射,获得定义类时声明的基类(父类)的泛型参数的类型.
接下来通过具体的实例来分析整合过程,使用一个用户表ad_user包含字段id、username、password。
4、根据表建立实体bean和mybatis的sql.xml文件配置
User类需要继承BaseEntity
user.sqlMap.xml的配置信息如下:
UserDao的实现,需要继承MyBatisDao,在UserDao中可以扩展自己的方法,@Repository注解表示该层为存储层。
UserService类业务层类,@Service表示该层为服务层,@Transactional放在类上表示每个公有方法都受事物管理,具体的管理方式在spring的配置文件中提现。
5、配置文件的分析
最主要的配置文件是applicationContext.xml,具体说明见代码中的注释部分
db.properties文件用于配置数据库连接信息
ehcache-application.xml用于配置缓存信息
log4j.properties用于配置日志信息
mybaits.sqlMap.xml无实际作用,这个里面的配置信息都在spring配置文件中进行配置了
6、测试的类TestMain
具体的项目代码见附件!
2、首先看整个的工程包的截图
3、先来分析spring.mybatis.orm包下的类
1)、SqlMapl类属于数据库标识接口,用于spring中的配置使用。
package spring.mybatis.orm; /** * 数据库访问标识接口 *@author TonyJ *@time 2015-1-31 下午03:41:17 *@email tanglongjia@126.com */ public interface SqlMap { }
2)、BaseSqlMap类,操作数据库的通用方法接口
package spring.mybatis.orm; /** *@author TonyJ *@time 2015-1-31 下午03:45:52 *@email tanglongjia@126.com */ public interface BaseSqlMap<T extends BaseEntity> extends SqlMap { /** * 保存 */ public static final String SQL_INSERT=".insert"; /** * 删除 */ public static final String SQL_DELETE=".delete"; /** * 更新 */ public static final String SQL_UPDATE=".update"; /** * 根据Id查询 */ public static final String SQL_SELECT_SINGLE = ".selectSingle"; /** * 查询单个 * @param param * @return */ T selectSingle(Object param); /** * 保存 * @param entity * @return */ T insert(T entity); /** * 更新 * @param entity * @return */ boolean update(T entity); /** * 删除一个 * @param param * @return */ boolean delete(Object param); }
3)、BaseEntity类,通用的实体类定义一些通用的属性
package spring.mybatis.orm; import java.io.Serializable; import java.util.Date; /** *@author TonyJ *@time 2015-1-31 下午03:37:46 *@email tanglongjia@126.com */ public class BaseEntity implements Serializable,Cloneable { /** * */ private static final long serialVersionUID = 2413960745071474764L; /** *标识Id */ private long id; /** * 用户名 */ private String userName; /** * 创建时间 */ private Date createTime; /** * 更新时间 */ private Date updateTime; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } }
4)、MyBatisDao类,通用方法的实现类
package spring.mybatis.orm; import org.apache.ibatis.session.SqlSession; import org.apache.log4j.Logger; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import spring.mybatis.utils.ReflectHelper; /** *@author TonyJ *@time 2015-1-31 04:43:08 *@email tanglongjia@126.com */ public class MyBatisDao<T extends BaseEntity> implements BaseSqlMap<T> { private static final Logger logger = Logger.getLogger(MyBatisDao.class); protected Class<T> entityClass; @Autowired protected SqlSessionTemplate sqlSession; @SuppressWarnings("unchecked") public MyBatisDao(){ this.entityClass = ReflectHelper.getSuperClassGenericType(getClass(), 0); } public SqlSession getSqlSession(){ return sqlSession; } public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } @Override public T selectSingle(Object param) { if(null == param){ logger.error("非法参数:param为空!"); throw new IllegalArgumentException("非法参数:param为空!"); } T result = null; try{ result = getSqlSession().selectOne(entityClass.getName()+SQL_SELECT_SINGLE, param); }catch(Throwable e){ logger.error(e); } return result; } @Override public T insert(T entity) { if(null == entity){ logger.error("参数对象为null!"); throw new IllegalArgumentException("参数不可为null!"); } try{ getSqlSession().insert(entityClass.getName()+SQL_INSERT, entity); }catch(Throwable e){ logger.error(e); return null; } return entity; } @Override public boolean update(T entity) { if(null == entity){ throw new IllegalArgumentException("参数不可为null!"); } try{ getSqlSession().update(entityClass.getName()+SQL_UPDATE, entity); } catch (Exception e) { logger.error("更新数据异常:", e); return false; } return true; } @Override public boolean delete(Object param) { try{ getSqlSession().delete(entityClass.getName()+SQL_DELETE, param); }catch (Exception e) { logger.error("删除数据异常:",e); return false; } return true; } }
5)、ReflectHelper类,工具类,通过java反射,获得定义类时声明的基类(父类)的泛型参数的类型.
package spring.mybatis.utils; /* * 文件名:ReflectHelper.java * * �? 能: 利用java反射机制,提供访问类的详细信息和类对象的工具方法�? * �? 名: ReflectHelper * **/ import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import org.apache.log4j.Logger; /** * * <b>本类�?利用java反射机制,提供访问类的详细信息和类对象的工具类�? * </b><br><br> * <em> * <b>功能�?/b>利用java反射机制,提供访问类的详细信息和类对象的工具方法�? * * </em> * */ public class ReflectHelper { private static final Logger log = Logger.getLogger(ReflectHelper.class); /** * 获取obj对象fieldName的Field * @param obj * @param fieldName * @return */ public static Field getFieldByFieldName(Object obj, String fieldName) { for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass .getSuperclass()) { try { return superClass.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { } } return null; } /** * 获取obj对象fieldName的属性�? * @param obj * @param fieldName * @return * @throws SecurityException * @throws NoSuchFieldException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static Object getValueByFieldName(Object obj, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field field = getFieldByFieldName(obj, fieldName); Object value = null; if(field!=null){ if (field.isAccessible()) { value = field.get(obj); } else { field.setAccessible(true); value = field.get(obj); field.setAccessible(false); } } return value; } /** * 设置obj对象fieldName的属性�? * @param obj * @param fieldName * @param value * @throws SecurityException * @throws NoSuchFieldException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static void setValueByFieldName(Object obj, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field field = obj.getClass().getDeclaredField(fieldName); if (field.isAccessible()) { field.set(obj, value); } else { field.setAccessible(true); field.set(obj, value); field.setAccessible(false); } } /** * 通过java反射,获得定义类时声明的基类(父类)的泛型参数的类型. * 如类声明:public UserDao extends HibernateDao <com.mass.demo.User> ...,�? * 调用本方法语句getSuperClassGenericType(UserDao.class,0)返回User.class. * * @param clazz - 子类Class * @param index - 基类层级 * @return 基类(父类)的泛型参数的类型 */ @SuppressWarnings("unchecked") public static Class getSuperClassGenericType(final Class clazz, final int index){ Type genericType = clazz.getGenericSuperclass(); if(!(genericType instanceof ParameterizedType)){ return Object.class; } Type[] params = ((ParameterizedType) genericType).getActualTypeArguments(); if(index>=params.length || index < 0){ log.warn("Index:"+index+",size of "+clazz.getSimpleName()+"'s Parameterize Type:"+params.length); return Object.class; } if(!(params[index] instanceof Class)){ return Object.class; } return (Class)params[index]; } }
接下来通过具体的实例来分析整合过程,使用一个用户表ad_user包含字段id、username、password。
4、根据表建立实体bean和mybatis的sql.xml文件配置
User类需要继承BaseEntity
package spring.mybatis.bean; import spring.mybatis.orm.BaseEntity; /** *@author TonyJ *@time 2015-1-31 下午04:57:54 *@email tanglongjia@126.com */ public class User extends BaseEntity { /** * */ private static final long serialVersionUID = 6305819764075546164L; /** * 密码 */ private String password; public void setPassword(String password) { this.password = password; } public String getPassword() { return password; } }
user.sqlMap.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="spring.mybatis.bean.User"> <resultMap type="spring.mybatis.bean.User" id="userResult"> <result property="id" column="id" jdbcType="INTEGER" javaType="java.lang.Integer" /> <result property="userName" column="username" /> <result property="password" column="password" /> </resultMap> <select id="selectSingle" parameterType="int" resultMap="userResult"> select username,password,id from ad_user where id=#{id} </select> <select id="getAll" resultMap="userResult"> select username,password,id from ad_user </select> <insert id="insert" parameterType="user"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> select _nextval('ad_user_seq') </selectKey> <![CDATA[ insert into ad_user(id,username,password) values(#{id},#{userName},#{password}) ]]> </insert> <update id="update" parameterType="user"> update ad_user set username=#{userName},password=#{password} where id=#{id} </update> <delete id="delete" parameterType="int"> delete from ad_user where id=#{id} </delete> </mapper>
UserDao的实现,需要继承MyBatisDao,在UserDao中可以扩展自己的方法,@Repository注解表示该层为存储层。
package spring.mybatis.dao; import java.util.List; import org.springframework.stereotype.Repository; import spring.mybatis.bean.User; import spring.mybatis.orm.MyBatisDao; /** *@author TonyJ *@time 2015-2-2 下午08:53:40 *@email tanglongjia@126.com */ @Repository public class UserDao extends MyBatisDao<User> { public List<User> getAll(){ return this.getSqlSession().selectList("getAll"); } }
UserService类业务层类,@Service表示该层为服务层,@Transactional放在类上表示每个公有方法都受事物管理,具体的管理方式在spring的配置文件中提现。
package spring.mybatis.service; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import spring.mybatis.bean.User; import spring.mybatis.dao.UserDao; /** *@author TonyJ *@time 2015-2-2 下午08:55:04 *@email tanglongjia@126.com */ @Service @Transactional public class UserService { @Autowired private UserDao userDao; public User getUserById(Long id){ Map<String,Long> param = new HashMap<String,Long>(); param.put("id", id); return userDao.selectSingle(param); } public List<User> getAll(){ return userDao.getAll(); } }
5、配置文件的分析
最主要的配置文件是applicationContext.xml,具体说明见代码中的注释部分
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/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"> <!-- 数据库配置文件位置 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 配置dbcp数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 队列中的最小等待数 --> <property name="minIdle" value="${jdbc.minIdle}"></property> <!-- 队列中的最大等待数 --> <property name="maxIdle" value="${jdbc.maxIdle}"></property> <!-- 最长等待时间,单位毫秒 --> <property name="maxWait" value="${jdbc.maxWait}"></property> <!-- 最大活跃数 --> <property name="maxActive" value="${jdbc.maxActive}"></property> <property name="initialSize" value="${jdbc.initialSize}"></property> </bean> <!-- 配置SqlSessionFactoryBean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- mapper和resultmap配置路径 --> <property name="mapperLocations"> <list> <!-- 表示在spring.mybatis.bean包或以下所有目录中,以sqlMap.xml结尾所有文件 --> <value>classpath:spring/mybatis/bean/*sqlMap.xml</value> </list> </property> </bean> <!-- 配置事务的传播特性--> <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="edit*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="insert*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="del*">PROPAGATION_REQUIRED</prop> <prop key="*">readOnly</prop> </props> </property> </bean> <!-- 通过扫描的模式,扫描目录在spring/mybatis/目录下,所有的mapper都继承SqlMapper接口的接口, 这样一个bean就可以了 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="spring.mybatis"/> <property name="markerInterface" value="spring.mybatis.orm.SqlMap"/> </bean> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> <!-- 采用注释的方式配置bean --> <context:annotation-config /> <!-- 配置要扫描的包 --> <context:component-scan base-package="spring.mybatis"></context:component-scan> <!--proxy-target-class="true"强制使用cglib代理 如果为false则spring会自动选择--> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 使用annotation注解方式配置事务 --> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
db.properties文件用于配置数据库连接信息
dialect=MYSQL jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc\:mysql\://localhost\:3306/cmsp jdbc.username=test jdbc.password=test jdbc.maxActive = 2 jdbc.maxIdle =5 jdbc.minIdle=1 jdbc.initialSize =3 jdbc.maxWait =3000
ehcache-application.xml用于配置缓存信息
<?xml version="1.0" encoding="UTF-8"?> <ehcache> <diskStore path="java.io.tmpdir" /> <cacheManagerEventListenerFactory class="" properties=""/> <!-- DefaultCache setting. --> <defaultCache maxElementsInMemory="100000" eternal="true" overflowToDisk="true" diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000" timeToIdleSeconds="130" timeToLiveSeconds="140" memoryStoreEvictionPolicy="LRU" /> </ehcache>
log4j.properties用于配置日志信息
log4j.rootLogger=debug,stdout,fout log4j.logger.org.apache.ibatis=ERROR log4j.logger.java.sql=debug,stdout log4j.logger.com.jsmass=DEBUG # SqlMap logging configuration... #log4j.logger.com.mybatis=DEBUG #log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG #log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG #log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG #log4j.logger.org.apache.commons=ERROR #log4j.logger.java.sql.Connection=DEBUG #log4j.logger.java.sql.Statement=DEBUG #log4j.logger.java.sql.PreparedStatement=DEBUG #log4j.logger.java.sql.ResultSet=DEBUG log4j.logger.com.ibatis=DEBUG log4j.logger.org.apache.ibais.jdbc.ScriptRunner=DEBUG #log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG #log4j.logger.com.jsmass=DEBUG #log4j.logger.cn.jsmass=DEBUG #log4j.logger.cn.com.jsmass=DEBUG # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss},%6.6r]%-5p[%t]%x(%F:%L) - %m%n #File output log4j.appender.fout=org.apache.log4j.DailyRollingFileAppender log4j.appender.fout.file=C:/log/log4j.log log4j.appender.fout.layout=org.apache.log4j.PatternLayout log4j.appender.fout.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm\:ss},%6.6r]%-5p[%t]%x(%F\:%L) - %m%n
mybaits.sqlMap.xml无实际作用,这个里面的配置信息都在spring配置文件中进行配置了
<?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"> <!-- dtd约束,一定要拷过去啊。下面的根据具体应用,改改就可以了 --> <configuration> <!-- 指定与数据库相关的配置资源文件名,若下面的dataSource所需要的url等直接配置编码在此文件,那么此properties也可以去掉 --> <properties resource="db.properties"/> <!-- 给指定的类定义别名,这样在后面的Mapping映射文件中,可以直接写别名,可以不用写完整限定类名了 --> <typeAliases> <typeAlias alias="user" type="spring.mybatis.bean.User" /> </typeAliases> <environments default="default"> <environment id="default"> <transactionManager type="JDBC" /> <!-- JDBC事务管理 --> <dataSource type="POOLED"> <!-- 数据源 连接池相关 所需要数据库连接的相关配置信息,在db.properties有指定 --> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <!-- 映射文件 将sql、POJO、dao层映射连接在一起,以可配置的方式来组织。从此SQL的写法与dao层无关了。 --> <mappers> </mappers> </configuration>
6、测试的类TestMain
package spring.mybatis.test; import java.util.List; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import spring.mybatis.bean.User; import spring.mybatis.dao.UserDao; /** *@author TonyJ *@time 2015-2-2 下午08:57:56 *@email tanglongjia@126.com */ public class TestMain { @Test public void userServiceTest(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao dao = context.getAutowireCapableBeanFactory().getBean("userDao", UserDao.class); /* Map<String, Long> param = new HashMap<String, Long>(); param.put("id", new Long(12)); User user = dao.selectSingle(param); System.out.println(user.getUserName());*/ List<User> userList = dao.getAll(); for (User user : userList) { System.out.println("id : " + user.getId() + ",userName : " + user.getUserName() + ",password : " + user.getPassword()); } } }
具体的项目代码见附件!
下一篇: 求一段php+mysql防流入代码
推荐阅读
-
spring和mybatis泛型接口的整合(一)
-
一篇超详细的Spring Boot整合Mybatis文章
-
Spring和MyBatis整合自动生成代码里面text类型遇到的坑
-
Spring和MyBatis整合自动生成代码里面text类型遇到的坑
-
Mybaits 源码解析 (十二)----- Mybatis的事务如何被Spring管理?Mybatis和Spring事务中用的Connection是同一个吗?
-
Spring和Mybatis整合需要导入的依赖
-
@Autowired 和 @Resource注解, 一个接口有多个实现类的时候Spring注入遇到的问题
-
MyBatis在DAO层定义接口返回类型泛型无效的解决
-
**Mybatis和Spring整合的时候 sqlSessionFactory出问题了!!求指点**
-
MyBatis与Spring的整合(传统的DAO方式和Mapper接口方式)