最近闲来无事看了些mybatis相关的知识。mybatis用起来还是很灵活的。看到网上也有许多这样的例子,但有的是不全的。下面我对mybatis+strut2+spring学习过程做一下总结(简单的环境搭建)。(@OnePage)
因为本人是初次写这样的文章,也是初学 有些不对的或写错的请指正。也请多多包含。
一、首先在数据库中建一个user表 。显示简单的基本信息就行。
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(11) DEFAULT NULL, `userAge` int(3) DEFAULT NULL, `userAddress` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
-- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', 'zhangsan1', '28', 'nihjaome'); INSERT INTO `user` VALUES ('2', 'tiana ', '20', '非洲'); INSERT INTO `user` VALUES ('3', 'arear', '20', 'mei洲');
二、建一个web项目。
1.配置web配置文件
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Spring监听 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name>
<!-- 引入spring的配置文件 如果有多个就用逗号分隔开--> <param-value>classpath:applicationContext-core.xml</param-value> </context-param> <!-- Struts2拦截器 --> <filter> <filter-name>Struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>Struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> </web-app>
2、配置spring application-code.xml文件 这里有两种配置 可以直接把数据库的链接就写到里面也可以配置到config.xml里面
当把数据连接写在spring配置文件里时 config.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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 数据源属性配置文件 --> <!-- <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:com/databaseconfig/database.properties"/> </bean> -->
<!-- 引入数据库配置信息的文件 这里我就不贴了--> <context:property-placeholder location="classpath:database.properties"/>
<!--数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${driverClassName}" /> <property name="jdbcUrl" value="${url}" /> <property name="user" value="${username}" /> <property name="password" value="${password}" /><!--
这里是一些数据库和缓存池的一些配置
<property name="autoCommitOnClose" value="true"/> <property name="checkoutTimeout" value="${cpool.checkoutTimeout}"/> <property name="initialPoolSize" value="${cpool.minPoolSize}"/> <property name="minPoolSize" value="${cpool.minPoolSize}"/> <property name="maxPoolSize" value="${cpool.maxPoolSize}"/> <property name="maxIdleTime" value="${cpool.maxIdleTime}"/> <property name="acquireIncrement" value="${cpool.acquireIncrement}"/> <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}"/> --></bean> <!-- 数据连接管理 --> <!-- ================================事务相关控制================================================= --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:advice id="TxAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException"/> <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="find*" propagation="SUPPORTS"/> <tx:method name="get*" propagation="SUPPORTS"/> <tx:method name="select*" propagation="SUPPORTS"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="AopTran" expression="execution (* com.hotel.dao..*.*(..))" /> <!--把事务控制在层--> <aop:advisor pointcut-ref="AopTran" advice-ref="TxAdvice" /> </aop:config> <!-- myBatis文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 引入config配置文件 如果数据连接在该配置文件里千万不要忘记-->
<property name="configLocation" value="classpath:myBatis-config.xml"/> <property name="dataSource" ref="dataSource"/> </bean> <!-- ibatis2.x 配置 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="classpath:myBatis-config.xml"/> <property name="dataSource" ref="dataSource"/> </bean> --> <!--<bean id="mapDao" class="org.mybatis.spring.MapperFactoryBean"> 这里是接口,不是接口实现类了 <property name="mapperInterface" value="com.ssm.iface.IUserDao"/> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> --> <!-- 自动扫描接口-->
<!-- 这里需要注意三点:
-
TeacherMapper mapper
-
= (TeacherMapper)ctx.getBean("userMapping"); 在main方法测试中用到
-->
<!-- 这里我们没有办法给MapperScannerConfigurer创建的这些映射器 指定id或name属性
然而下面的action 注入的时候又要用到注入的接口 我看了很多资料都不很详细
当action需要注入的接口时 需要的哪一个接口(但必须在指定的根包下 否则扫描不到的)就
<property name="InfaceMapp" ref="userMapping"></property> ref=“”里可以填写该接口类的名字(把第一个字母大写改成小写)扫描器就会自动的去扫描该接口
需要注入哪个接口就写哪个 或则个注解的方式填写@Component("userMapping")注解,在接口名字上面里面的填写的内容就是要对该action注入的名字。
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定要扫描的接口-->
<property name="basePackage" value="com.hotel.daoInface"></property>
</bean>
<!--如果不扫秒就需要指定接口 这里要写上 sqlSessionFactory 应为这个bean不会去自动装配数据的-->
<!-- <bean id="userMapping" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<property name="mapperInterface" value="com.hotel.daoInface.UserMapping">
</property>
</bean> -->
<!--访问的action -->
<bean id="loginAction" class="com.hotel.action.LoginAction">
<!-- 这里要注入的是MapperFactoryBean 的名字 或用MapperScannerConfigurer时定义的接口的名字
这里的ref是依赖上面定义的东西 我在这里出错了 一直报数据类型不匹配我把ref写成了value="userMapping"他就认为是一个字符串注入给了该接口 一时间看不出来还认为是其他配置地方出错了
耽搁两天没动出来我又一点点的注释掉验证才发现。
-->
<property name="InfaceMapp" ref="userMapping"></property>
</bean>
</beans>
3、mapping配置文件(如果用注解的方式直接把sql语句写到mapping接口里的话可以省略)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 里写上接口的全路径-->
<mapper namespace="mybatis.mapper.UserMapping"> <select id="selectUserById" parameterType="int" resultType="User"> select * from user where id = #{id} </select> <resultMap type="User" id="resultListUser"> <!-- 经验证如果bean的属性与数据里的没有配置的话会默认读取 对应的话要类型对应 column是对应的数据库里字段 如果不相同就认为对应的值找不到 就会自动去寻找相同的 如果里面没有配置的话也会自动去匹 配 如果需要的话可以指定值的 --> <id column="id" property="id"/> <result column="userName" property="userName"/> <result column="userAge" property="userAge"/> <result column="userAddress" property="userAddress"/> </resultMap> <!--关联查询的例子 --> <!--<resultMap type="mybatis.bean.Article" id="ArticleuserList"> <id column="id" property="aid"/> <result column="titile" property="title"/> <result column="content" property="content"/> <association property="user" javaType="User"> <id column="id" property="id"/> <result column="userName" property="userName"/> <result column="userAge" property="userAge"/> <result column="userAddress" property="userAddress"></result> </association> </resultMap> --><!-- 关联这样可以用 --> <resultMap type="mybatis.bean.Article" id="ArticleuserList"> <id column="id" property="aid"/> <result column="titile" property="title"/> <result column="content" property="content"/> <association property="user" resultMap="resultListUser" javaType="User"/> </resultMap> <!-- select 的返回类型可以是resultType="User" 也可以应用外面的 resultMap="resultListUser"的之定义的名字id--> <select id="selectAllUser" resultType="User" > select * from user </select> <select id="selectUserByName" resultMap="resultListUser" parameterType="string"> <!-- 类名不对的话会报错 Table 'mybatis.username' doesn't exist --> <!-- 模糊查询 现在只能是在传参的时候加上%name% 在配置文件上试了几种不行 --> select * from user where userName like #{userName} </select> <insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id"> insert into user (userName ,userAge,userAddress) values(#{userName},#{userAge},#{userAddress}); </insert> <update id="updateUser" parameterType="User"> update user set userName=#{userName},userAge=28,userAddress="nihjaome" where id=#{id} </update> <delete id="deleteUserByname" parameterType="string"> delete from user where userName=#{userName} </delete> <select id="selectArtcle" parameterType="int" resultMap="ArticleuserList"> select u.userName,u.userAge,u.userAddress, a.titile,a.content from user u ,article a where u.id=a.userId and userId=#{userId} </select> </mapper>
config.xml代码
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- 配置内容 --> <configuration> <!-- 导入配置链接数据可的账号密码文件 --> <properties resource="jdbc.properties"></properties> <!-- 类别名 指定的类型 别名是为 Java 类型命名一个短的名字。 它只和 XML 配置有关, 只用来减少类完全 限定名的多余部分 使用这个配置, “Blog”可以任意用来替代“domain.blog. Blog”所使用的地方。 You can also specify a package where MyBatis will search for beans. For example: <typeAliases> <typeAlias alias="Author" type="domain.blog.Author"/> <typeAlias alias="Blog" type="domain.blog.Blog"/> <typeAlias alias="Comment" type="domain.blog.Comment"/> <typeAlias alias="Post" type="domain.blog.Post"/> <typeAlias alias="Section" type="domain.blog.Section"/> <typeAlias alias="Tag" type="domain.blog.Tag"/> </typeAliases> <typeAliases> <package name="domain.blog"/> </typeAliases> --> <!-- 类别名 这个在usermapping.xml是可以用到的resultMap 里面的type= 如果这里不写type就要写全的类名 --> <typeAliases> <typeAlias alias="User" type="com.hotel.bean.User"/> </typeAliases> <!-- 建立对数据库的链接 环境environments平台 默认的环境 ID(比如:default=”development”)。 每个 environment 元素定义的环境 ID(比如:id=”development”)。 事务管理器的配置(比如:type=”JDBC” )。 数据源的配置(比如:type=”POOLED”)。 UNPOOLED – 这个数据源的实现是每次被请求时简单打开和关闭连接。它有一点慢, 这是对简单应用程序的一个很好的选择, 因为它不需要及时的可用连接。 不同的数据库对这 个的表现也是不一样的, 所以对某些数据库来说配置数据源并不重要, 这个配置也是闲置的。 UNPOOLED 类型的数据源仅仅用来配置以下 5 种属性: POOLED – 这是 JDBC 连接对象的数据源连接池的实现,用来避免创建新的连接实例 时必要的初始连接和认证时间。这是一种当前 Web 应用程序用来快速响应请求很流行的方 法。 JNDI – 这个数据源的实现是为了使用如 Spring 或应用服务器这类的容器, 容器可以集 中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这个数据源配置只需要两个属 性: initial_context – 这 个 属 性 用 来 从 初 始 上 下 文 中 寻 找 环 境 ( 也 就 是 initialContext.lookup(initial——context) 。这是个可选属性,如果被忽略,那么 data_source 属性将会直接以 initialContext 为背景再次寻找。 data_source – 这是引用数据源实例位置的上下文的路径。它会以由 initial_context 查询返回的环境为背景来查找,如果 initial_context 没有返回结果时,直接以初始 上下文为环境来查找。 --> <!--<environments default="development"> <environment id="development"> JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。 它依赖于从数据源得 到的连接来管理事务范围。 MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。 而它会让 容器来管理事务的整个生命周期(比如 Spring 或 JEE 应用服务器的上下文) 默认 情况下它会关闭连接。 然而一些容器并不希望这样, 因此如果你需要从连接中停止 它,将 closeConnection 属性设置为 false。例如: <transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}" /> <property name="username" value="${username}"/> <property name="password" value="${password}"/> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root"/> <property name="password" value="liule"/> </dataSource> </environment> </environments> --><!--既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。 但是, 首先我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在这方面没有提供一个很好 的方法, 所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的 资源引用,或者字符表示,或 url 引用的完全限定名(包括 file:///URLs) 。 这些语句简单告诉了 MyBatis 去哪里找映射文件。其余的细节就是在每个 SQL 映射文 件中了,下面的部分我们来讨论 SQL 映射文件。 --><!-- -->
<mappers> <mapper resource="com/hotel/bean/User.xml"/> </mappers> </configuration>
接口userMapping
package com.hotel.daoInface; import java.util.List; import org.apache.ibatis.annotations.Select; import com.hotel.bean.User; // @Component("userMapping") public interface UserMapping { @Select("select * from user ")//利用注解的方式写sql语句在mapping配置文件里就不用写 public List<User> findUserList(); public List<User> selectUserByName(String username); public void addUser(User user); public void updateUser(User user); public void deleteUserByname(String userName); }
test 测试类 这里只是简单的行数据测试 但还没有加入struts测试(去web中访问测试)
package test; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.hotel.bean.User; import com.hotel.daoInface.UserMapping; public class Test { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("classpath:applicationContext-core.xml"); UserMapping userMapping= (UserMapping) ctx.getBean("userMapping");//这里的“”里面的内容就是扫描时接口的名字。 //当时是没有想到这个名字就是注入到action里面ref=“”的名字 。当时还纳闷的 这么多
//接口扫描器怎样去区分呢?原来就在这个接口的名字上有猫腻呢,把接口的名字首字母改成小写就是扫描到该接口的对象。 List<User> u1=(List<User>) userMapping.findUserList(); for(User user : u1 ){ System.out.println(user.getUserName());//打印出名字。 } } }
struts配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="login" namespace="/login" extends="json-default"> <action name="login" class="loginAction"> <result name="success"> ../login.jsp </result> </action> </package> </struts>
action 类文件
package com.hotel.action; import java.util.List; import com.hotel.bean.User; import com.hotel.daoInface.UserMapping; public class LoginAction { private UserMapping InfaceMapp; public String execute(){ List<User> user= InfaceMapp.findUserList(); for(User u:user){ System.out.println("user" + u.getId()+"../."+u.getUserName()); } return "success"; } public UserMapping getInfaceMapp() { return InfaceMapp; } public void setInfaceMapp(UserMapping infaceMapp) { InfaceMapp = infaceMapp; } }
细心地 人会发现我这里有dao 包和daoimpl包 其实这两个我都没有用
我看着有些资料上都用着 这两个包就是在开发上编辑逻辑代码用的一个接口 一个时间接口。相当于service。我这里是简单的例子就没有用。
jsp页面代码。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> </head> <body> <p>Welcome login in </p> <br/><P>我并没有把收到的数据拿到页面上来只是在控制台打印了一下</p> </body> </html>
基本就是这些内容。有些不对的或写错的请提出来,也请多多包含。
MapperScannerConfigurer是参考 : http://legend2011.blog.51cto.com/3018495/980150