学习mybatis及Springmvc的一些笔记

Mybatis:

一个基本配置文件

 Configuration.xml 主要是用来配置mybatis的行为以及数据库的连接信息

Mappers是映射器,基本上是写一个实体类就有一个相应的sql操作xml文档,所以也就是多个映射器。

Environment是环境id,默认的环境和环境 ID 是一目了然的。随你怎么命名,只要保证默认环境要匹配其中一个环境ID。

映射的sql文档

ParameterType可以省略

#{id} 当id的值被传入这个sql语句时把id当成一个?号,#把id的值自动加上双引号,并进行预编译相当于执行prepareStatement()语句,#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。

使用

扫描二维码关注公众号,回复: 3140610 查看本文章

Mybatis返回一个list记录所有结果

xml映射

<mappernamespace="com.yihaomen.mybatis.models.UserMapper">

         <resultMap type="User"id="UserList">
                   <resultproperty="id" column="id" />
                  <resultproperty="userName" column="userName"/>
                   <resultproperty="userAge" column="userAge" />
                   <resultproperty="userAddress" column="userAddress"/>
         </resultMap>


    <selectid="selectUserByID" resultMap="UserList">
        select * from `user`
    </select>

</mapper>

首先说一下sqlSession.selectOne()函数,它只能查询一条数据,如果表中的记录多于一条就会报错,空数据不会报错,也就是说当表中有一条或者没有数据时都会正常执行。

但如果想查询多条结果呢,就需要指定resultMap了,不仅要添加resultMap,还要在下面的sql具体语句中将resultType给改为resultMap

使用;

 java.util.List<User>L = session.selectList("com.yihaomen.mybatis.models.UserMapper.selectUserByID");
        for (User u : L) {
                System.out.println(u.getId()+u.getUserName()+u.getUserAge()+u.getUserAddress());}

mybatis使用接口编程

1.     通过在接口中添加注解的方式

   package com.yihaomen.mybatis.inter;

importorg.apache.ibatis.annotations.Select;

import com.yihaomen.mybatis.model.User;;

public interface IUserOperation {

         @Select("select* from User where id=#{id}")

         public UserselectUserByID(int id);

}

*一个xml映射似乎只能放一个映射器mapper,mappers只能在mybatis的基本配置Configuration中出现,不能在xml映射中出现。

添加完成注解后,

</mapper>

         <mappernamespace="com.yihaomen.mybatis.inter.IUserOperation"></mapper>

</mappers>

Xml映射如上,就没有了sql语句,调用时正常调用就行

IUserOperation iUserOperation = session.getMapper(IUserOperation.class);

     User u =iUserOperation.selectUserByID(1);

 System.out.println(u.getUserName()+u.getUserAddress());

2.  通过xml+dao的方式

Dao层代码:只实现了方法名不需要方法体

package com.yihaomen.mybatis.inter;

import org.apache.ibatis.annotations.Select;

import com.yihaomen.mybatis.model.User;;

public interface IUserOperation {

         public UserselectUserByID(int id);

}

Xml:select id需要与接口里的方法一致

<mappernamespace="com.yihaomen.mybatis.inter.IUserOperation" >

         <selectid="selectUserByID" resultType="User">

        select *from `user` where id = #{id}

    </select>

         </mapper>

调用无变化

 

增删改

Insert:

Xml映射文档insert和update中有useGeneratedKeys、keyProperty、keyColumn,如果表中的有数据是自增的,使用useGeneratedKeys来设定为true,keyProperty是指定自增的列名,keyColumn是当第一个字段不是自增是使用。

Xml映射文档:

<mapper namespace="com.yihaomen.mybatis.inter.IUserOperation">

    <select id="selectUserByID" resultType="User">

        select * from `user` where id = #{id}

    </select>

   

    <insert id="insertUser" parameterType="User" >

    insertinto user (id,userName,userAge,userAddress) values(#{id},#{userName},#{userAge},#{userAddress})

    </insert>

    </mapper>

Dao层:

import com.yihaomen.mybatis.model.User;;

public interface IUserOperation {

    public User selectUserByID(intid);

    public void insertUser(User u);

}

 

调用时需要注意,sqlsession有一个commit()函数,需要提交一下:,增加后,必须提交事务,否则不会写入到数据库.

public static void main(String[] args) {

        SqlSession session = sqlSessionFactory.openSession();

        try{

      

        IUserOperation iUserOperation =session.getMapper(IUserOperation.class);

        User u =iUserOperation.selectUserByID(1);

        System.out.println(u.getUserName()+u.getUserAddress());

       

        User u1 = newUser();

        u1.setId(14);

        u1.setUserAddress("aaa");

        u1.setUserAge("42");

        u1.setUserName("12wq");

        iUserOperation.insertUser(u1);

        session.commit();

                } finally{

        session.close();

        }

}

 

 

Update:也需要commit()

Xml配置文件:

    <update id="updateUser" parameterType="User">

         updateUser set UserName = #{userName} where id=#{id}

</update>

Dao层:

public void updateUser(User u);

调用:

  User u2 = newUser();

        u2.setId(14);

        u2.setUserName("qqqq");

       iUserOperation.updateUser(u2);

    session.commit();

 

delete:与上面类似

 

多表查询:多对一,例如有用户表和文章表,一个用户可以发表多个文章。

这个时候就需要resultMapassociation来结合使用了。文章表中有用户的id,这个时候虽然文章表中只有用户的属性,在建立实体类封装时依然要给文章这个类存入User,而不是Userid

多表查询xml映射有两种配置方法:

(1)将一的result写入association中,把association放入多的resultMap

 

这里存在一个问题,如果数据库中的文章表的字段和用户的字段一样的(如上面的id),mybatis就只能查出第一条数据,怎么解决呢?在xml的映射中resultMap里把column设置成别名,在下面的select的sql的语句里相应部分也给设成别名。如下面的xml映射就将article的id设置了别名(另:property应该是数据库或者实体类中的字段名,column可以修改应该是mybatis映射的字段名):

<mapper namespace="com.yihaomen.mybatis.inter.IUserOperation">

    <resultMap  type="Article"id="resultMapList">

        <id property="id"column="aid"/>

        <result property="title" column="title"/>

        <result property="content" column="content"/>

        <association property="user" javaType="User">

         <id property="id" column="id"/>

         <result property="userName" column="userName"/>

          <result property="userAge" column="userAge"/>

           <result property="userAddress" column="userAddress"/>

        </association>

    </resultMap>

    <select id="selectArticleUser" resultMap="resultMapList">

        select user.userName,user.userAddress,article.id aid fromuser,article

        where user.id=article.userid ;

    </select>

</mapper>

 

(2)xml映射的第二种写法:

将一的内容写入resultMap中,放在多的内容外,多的内容除了写多的内容,只加入association,而association中不用再加入内容,但是需要在association中多设置一个resultmap指向刚设置好的一的resultmapid

<resultMap id="usermap" type="User">

        <result property="id" column="id"/>

        <result property="userName" column="userName"/>

        <result property="userAge" column="userAge"/>

        <result property="userAddress" column="userAddress"/>

    </resultMap>

   

    <resultMap type="Article" id="articleMap">

        <result property="id" column="aid"/>

        <result property="title" column="title"/>

        <result property="content" column="content"/>

        <association property="user" javaType="User"resultMap="usermap" />

    </resultMap>

    <select id="selectArticleUser" resultMap="articleMap">

        select user.userName,user.userAddress,article.id aid fromuser,article

        where user.id=article.userid ;

</select>

 

两种映射的比较,第二种方法相当于把association里面的内容给抽取出来了,这样别的resultMap也可以使用

 

 

 

Dao层:publicList<Article> selectArticleUser();

调用:

        List<Article> articles =iUserOperation.selectArticleUser();

        for(Articlearticle:articles){

            System.out.println(

                      "名字:"+article.getUser().getUserName()+""+"地址:"+article.getUser().getUserAddress()

                  +"文章内容:"+article.getContent()+articles.size());

        }

 

 

另:需要注意一点,如果调用时打印出在xml映射的selectsql中没有查的字段会打印出null,如上面articlecontent就是null

 

Mybatis 与 Spring的集合

在配置Spring的配置文件时遇到一个很恶心的事情,因为xml中的priperty配置时少些了一个斜杠,老是报

Caused by: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 18 in XML document from class path resource[config/applicationContext.xml] is invalid; nested exception isorg.xml.sax.SAXParseException; lineNumber: 18; columnNumber: 45;cvc-complex-type.2.4.a: 发现了以元素 'property' 开头的无效内容。应以 '{"http://www.springframework.org/schema/beans":description,"http://www.springframework.org/schema/beans":meta,"http://www.springframework.org/schema/beans":bean,"http://www.springframework.org/schema/beans":ref,"http://www.springframework.org/schema/beans":idref,"http://www.springframework.org/schema/beans":value,"http://www.springframework.org/schema/beans":null,"http://www.springframework.org/schema/beans":array,"http://www.springframework.org/schema/beans":list,"http://www.springframework.org/schema/beans":set,"http://www.springframework.org/schema/beans":map,"http://www.springframework.org/schema/beans":props, WC[##other:"http://www.springframework.org/schema/beans"]}'之一开头。

    at

这样的错误,一直以为是xml的头文件的引用错误,找了半天,最后终于发现了是少了一个斜杠引起的。

首先需要一个spring配置文件

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd 

           http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd 

           http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd 

           http://www.springframework.org/schema/jeehttp://www.springframework.org/schema/jee/spring-jee-3.0.xsd 

            http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsd" 

            default-autowire="byName"default-lazy-init="false">

 

<bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource">

     <property name="driverClassName" value="com.mysql.jdbc.Driver"/>

     <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>

    <property name="username" value="root"/> 

     <property name="password" value="root"/>

  </bean>

 

  <bean id="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">

     <!--dataSource属性指定要用到的连接池-->

     <property name="dataSource" ref="dataSource"/>

     <!--configLocation属性指定mybatis的核心配置文件-->

     <property name="configLocation" value="config/Configuration.xml"/>

  </bean>

 

  <bean id="userMapper"class="org.mybatis.spring.mapper.MapperFactoryBean">

     <!--sqlSessionFactory属性指定要用到的SqlSessionFactory实例-->

     <property name="sqlSessionFactory" ref="sqlSessionFactory" />

     <!--mapperInterface属性指定映射器接口,用于实现此接口并生成映射器对象-->

     <property name="mapperInterface" value="com.yihaomen.mybatis.inter.IUserOperation"/>

  </bean> </beans>

 

 

这里以applicationContext-mybatis.xml来体现,配置了如下信息:

 

注册数据源,常见的有JDBCJNDI,根据具体情况择一。

注册sqlSessionFactory

sqlSessionFactory是用来生产sqlSession以操作数据库的,所以,需指定sqlSessionFactory所引用的数据源

指定相应的SQL Mapper文件在哪里。我们自命名“_mapper后缀的xml文件”,主要用来定义SQL;“_resultmap后缀的xml文件”,则主要用来定义DB字段与应用程序实体属性的映射。

指定相应的应用程序实体在哪里,并自动注册不包含package名的别名

在哪些package下扫描Mapper接口,即DAO接口

 

调用:

private static ApplicationContext ctx;

   

    static{

        ctx = new ClassPathXmlApplicationContext("config/applicationContext.xml");

        //mybatis里这一步是加载configuration.xml,而在这里这一步变成了加载Spring的配置文件

    }

   

    public static void main(String []args){

        IUserOperation mapperIUserOperation = (IUserOperation) ctx.getBean("userMapper");

        //mybatis里这一步是使用sqlsessiongetMapper来加载接口的class文件,而在这却是使用Springxml配置的bean来找到那个接口

        System.out.print("--------------\n");

               

List<Article> arList =mapperIUserOperation.selectArticleUser();

       

        for (Article article : arList){

        System.out.println("--"+article.getContent()+"--"+article.getTitle()+"--"+article.getId()+"--"+article.getUser().getUserName());

           

        }

}

 

 

 

Mybatis与Spring与Springmvc的集合

Web.xml的配置信息

包含Spring的基本配置文档

包含Springmvc的分发器的基本文档

<context-param>

          <param-name>contextConfigLocation</param-name>

          <param-value>

              classpath*:config/applicationContext.xml

         </param-value>

     </context-param>

     <!-- 配置Spring上下文监听器,它的作用就是在启动WEB容器时,就会自动装在我们applicationContext.xml配置-->

     <listener>

         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

     </listener>

 

 

<servlet>

    <servlet-name>mvc-dispatcher</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>

            <param-name>contextConfigLocation</param-name>

            <param-value>classpath:config/springmvc-servlet.xml</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>

  </servlet>

  <servlet-mapping>

    <servlet-name>mvc-dispatcher</servlet-name>

    <url-pattern>/</url-pattern>

  </servlet-mapping>

 

Spring的Applicationcontext.xml文档

包含数据库的配置

包含一些service层的注册bean

包含sqlsession工厂的配置

包含与Spring集合的mybatis的基本文档信息

包含接口的注册bean

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

        destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver"

        p:url="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8"

        p:username="root" p:password="root"

        >

</bean>

<context:component-scan base-package="com.test.service"/>

 

 

<bean id="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">

     <!--dataSource属性指定要用到的连接池-->

     <property name="dataSource" ref="dataSource"/>

     <!--configLocation属性指定mybatis的核心配置文件-->

     <property name="configLocation" value="classpath:config/Configuration.xml"/>

 

<!-- 所有配置的mapper文件  通过ClassPathXmlApplicationContextgetbean()时传入小写的接口名 -->

     <property name="mapperLocations" value="classpath*:com/test/mapper/*.xml" />

  </bean>

 

Mybatis的配置信息

包含实体类的别名配置

<configuration>

    <typeAliases>

        <typeAlias alias="User" type="com.test.model.User"/>

        <typeAlias alias="Article" type="com.test.model.Article"/>

    </typeAliases>

</configuration>

映射Xml

 

 

调用:

@Controller

@RequestMapping("/mvc")

public class UserController {

    @Autowired

 

    ArticleInter art;

    @RequestMapping("/list")

    @ResponseBody

    public void show (HttpServletRequest request,HttpServletResponse response) throwsIOException{

       

        PrintWriter pw = response.getWriter();

           List<Article>list = art.getListArticle();

           for(Article article : list) {

        System.out.println(article.getId()+"--"+article.getTitle()+article.getContent()+"--"+article.getUser().getUserAddress());

        pw.write(article.getId()+"--"+article.getTitle()+article.getContent()+"--"+article.getUser().getUserAddress());

           

       

        pw.write("123");

    }

}

}

 

遇到一个问题,在运行时一直报接口的方法的空指针的错误,调试之后发现接口的值为空,

十一月 16, 2017 1:23:44 下午 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet [mvc-dispatcher] in context with path [/TheNewTest] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at com.test.controller.UserController.show(UserController.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

后来发现是少了@Autowired,它的作用是对于bean当中引用的其他bean不需要我们自己去配置它该使用哪个类,Spring 的自动装配可以帮助我们完成这些工作。

 



猜你喜欢

转载自blog.csdn.net/qq_35201754/article/details/78550099