一.JavaWeb中service层的作用

MVC = Jsp + Servlet + JavaBean
其中jsp View,servlet Controller,javaBean 是一个可复用的java对象。BS项目
客户端发送请求 controller service dao
如果是CS项目
客户有一个界面【操作】 service dao
以上分析,BS 与 CS 的 service和dao都是一样的,这样分层,代码复用,而且容易多人协作开发。DAO:最听话的,让你**增删改**你就增删改。没有情感,没有思想。
Controller:控制层,接收客户端请求的,客户端只能请求到servlet,不能请求到service,dao,其他
的java类。Controller的作用就是**接收客户端请求,调用其他java类**。如果要删除一个账号,谁去组织代码的逻辑呢?
这一层就是业务逻辑层,简称Service 层。
举例理解Service层
ATM机器上,你插入银行卡要给 小红 转账,1 元
【界面】转账进入转账界面输入对方的卡号输入转账金额确认按钮
【controller】可以一键生成的获取对方卡号,获取转账金额获取当前登录用户(session会话跟踪)
【service】需要程序员根据业务需求自行编写,设计规则//jdbc事务public void transfer(String fromNo,String toNo,int money){//判断对方卡号存不存在对方卡的状态对不对你的余额够不够updateMoney(toNo,1);//停电了....updateMoney(fromNo,-1);给你发短信给对方发短信给你的微信公众号发消息添加转账记录.....}
【dao】可以一键生成的public void updateMoney(String cardNo,int money);

举例2

注册账号:
【界面】填写你的账号输入两次密码手机验证码可选的(越来越多,短信不能随便发了)
【controller】 servlet(springMVC)try{接收数据 String数据封装,数据类型转换,封装为实体对象调用--》service显示结果-->请求转发/重定向到页面 或者 输出的是json}catch(Exception e){//对异常进行显示即可String msg = e.getMessage();request.setAttribute("msg",msg);//请求转发到注册jsp,jsp ${msg}//如果前端是ajax//response.getWrite().print("{result:false,msg:“+msg+”}");}
【service】业务逻辑
public void register(Account account){//判断,非空判断,长度判断,密码安全性判断【前端不是有js判断,前端判断对程序员无效】throw new RuntimeException("密码长度不足6位");//两次密码一致性判断throw new RuntimeException("两次密码不一致");//用户名or手机号是否被注册判断....//密码进行加密储存--> MD5【前端传输数据的时候就已经进行MD5的加密了】//调用dao保存数据//日志,xxx 什么 时间 xxx 注册了,什么 ip//发送短信
}
【dao】public Account queryByName(String name){}public void save(Account account){}

二.MyBatis重要组件

小结mybatis开发步骤:

增加mybatis的依赖,mysql jar 的依赖编写mybatis-config.xml 核心配置文件【是mybatis运行的基础,mybatis所有的组件都是基于配置文
件运行的】编写model,实体类,编写mapper.xml映射文件【就是编写sql代码,达到sql和java代码分离以便于容
易的维护sql。以及提高sql的复用】使用mybatis提供的API,对数据库进行操作【接口,类很多】

1.Resources类

将文件读取为文件输入流。

注意事项:

// "mybatis-config.xml" 从当前类所在的包查找文件
// "/mybatis-config.xml" 从classes根目录下寻找
Resources类
将文件读取为 文件输入流
// "mybatis-config.xml" 从当前类所在的包查找文件
// "/mybatis-config.xml" 从classes根目录下寻找
InputStream resourceAsStream1 =
AccountMapperTest.class.getClass().getResourceAsStream("mybatis-config.xml");
System.out.println(resourceAsStream1);
//从classes根目录查找文件
//建议使用
InputStream resourceAsStream2 =
AccountMapperTest.class.getClassLoader().getResourceAsStream("mybatisconfig.xml");
System.out.println(resourceAsStream2);
//读取核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("mybatisconfig.xml");

反射方式读取文件

(1)、AppClass.class.getClassLoader().getResourceAsStream("file")

从类路径classpath,也就是classes根目录下读取文件。[推荐]

//1、读取核心配置文件
//InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
InputStream in = AccountMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

(2)、AppClass.class.getResourceAsStream(file)

// "mybatis-config.xml" 从当前类所在的包查找文件
// "/mybatis-config.xml" 从classes根目录下寻找//1、读取核心配置文件
//InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//InputStream in = AccountMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
InputStream in = AccountMapperTest.class.getResourceAsStream("/mybatis-config.xml");
//2、创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

上述三种方式都可,在MyBatis中推荐使用Resources类。

2.api的生命周期

注意api的生命周期

(1) SqlSessionFactoryBuilder

SqlSessionFactoryBuilder
构建sqlsessionfactory
一旦构建了sqlsessionfactory builder的作用就达到了,
builder生命周期 就是方法范围

(2) SqlSessionFactory

SqlSessionFactory
接口
这是一个重量级的对象,他的作用是获取sqlsession,是一本工厂设计模式,应该被设计为系统唯一。
如何去实现呢?
单例模式
静态块初始化【简单】
public interface SqlSessionFactory {SqlSession openSession();//使用最多的SqlSession openSession(boolean autoCommit);SqlSession openSession(Connection connection);SqlSession openSession(TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType);SqlSession openSession(ExecutorType execType, boolean autoCommit);SqlSession openSession(ExecutorType execType, TransactionIsolationLevellevel);SqlSession openSession(ExecutorType execType, Connection connection);Configuration getConfiguration();
}

(3) SqlSession

SqlSession
sql session
和数据库的一次会话,本质 connection+statement 。。PS
生命周期应该是方法内的,不能放在全局,类的属性都不行,而且特别还要注意用完即关闭,必须要关
闭,否则连接资源耗尽每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:
try (SqlSession session = sqlSessionFactory.openSession()) {// 你的应用逻辑代码
}

在所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭。

3.代码的改进

针对上面的点,对上次的代码进行改进

通过对mybaits提供的编程接口声明周期的理解,可以更好的组织程序代码。

package com.oracle.util;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.InputStream;/*** 编写mybatis的工具类,工具类最核心的就是为程序中各个mapper* 提供 sqlsession ,因为mapper要和 xml 打交道,打交道进行crud操作* 都是使用的sqlsession 提供的方法* <p>* 如何保证sqlsessionfactory是系统唯一呢?* 所谓单例 整个应用中,仅有一个类的实例存在*/
public class MybatisUtil {//私有化构造private MybatisUtil() {}//避免线程的不可见行private volatile static SqlSessionFactory sqlSessionFactory;public static SqlSessionFactory getSqlSessionFactory() {//双重锁if (sqlSessionFactory == null) {synchronized (MybatisUtil.class) {if (sqlSessionFactory == null) {try {//在这里初始化即可InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);} catch (Exception e) {System.err.println("初始化sqlsessionfactory异常:" + e.getMessage());System.exit(0);}}}}return sqlSessionFactory;}
}

现阶段mapper【以前的dao】代码编写

package com.oracle.mapper;import com.oracle.model.Account;
import com.oracle.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;import java.util.List;public class AccountMapper {public List<Account> selectAll(){SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();try {//查询多个用selectList,查询一个用selectOnereturn sqlSession.selectList("com.oracle.mapper.AccountMapper.selectAll");}finally {sqlSession.close();}}public Account selectById(Integer aid){SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();try {return sqlSession.selectOne("com.oracle.mapper.AccountMapper.selectById",aid);}finally {sqlSession.close();}}public void insert(Account account){SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();try {sqlSession.insert("com.oracle.mapper.AccountMapper.insert",account);}finally {sqlSession.close();sqlSession.commit();}}public void update(Account account) {SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();try {sqlSession.update("com.oracle.mapper.AccountMapper.update",account);sqlSession.commit();}finally {sqlSession.close();}}public void delete(Integer aid) {SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();try {sqlSession.update("com.oracle.mapper.AccountMapper.delete",aid);sqlSession.commit();}finally {sqlSession.close();}}}

AccountMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--mapper就是映射的意思--><!--namespace 命名空间,程序中通过 sql映射的唯一标识获取 sql,比如当前文件有一个 insert sql标识,但是
其他文件中也有一个insert sql标识,就无法区分了,所以不同的sql功能,操作,使用namespce进行区分-->
<!--建议namaspce的值 为 包名.文件名-->
<mapper namespace="com.oracle.mapper.AccountMapper"><!--查询  --><!--sql代码--><!--mybatis中提供了四个最基础的sql标签,增删改查--><!--id是程序中获取sql的标识,完整的标识是 namespace.sqlID--><!--resultType 结果返回类型--><select id="selectAll" resultType="com.oracle.model.Account">select aid,aname,apassword,a_nickname as anikename from account</select><!--通过id查询,#{} 占位符,程序会自动根据参数的类型,选择是否增加 '' --><select id="selectById" resultType="com.oracle.model.Account">select aid,aname,apassword,a_nickname as anikename from account where aid=#{aid}</select><!--下面的insert语句中 #{} 中写的是对象的属性--><!--下面的insert语句中 #{} 中写的是对象的属性--><insert id="insert">insertintoaccount(aname,apassword,a_nickname)values(#{aname},#{apassword},#{anikename})</insert><update id="update">update accountset aname = #{aname}, apassword = #{apassword}, a_nickname = #{anickname}where aid = #{aid}</update><delete id="delete">delete from accountwhere aid = #{aid}</delete></mapper>

AccountMapperTest.java

package com.oracle.mapper;import com.oracle.model.Account;
import org.junit.Before;
import org.junit.Test;import java.util.List;public class AccountMapperTest4 {private AccountMapper accountMapper;@Beforepublic void before() {accountMapper = new AccountMapper();}@Testpublic void selectAll(){List<Account> list = accountMapper.selectAll();System.out.println(list);/*** [Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}, Account{aid=2, aname='lisi', apassword='123456', anikename='李四'},* Account{aid=4, aname='wangwu', apassword='123456', anikename='王五'}]* */}@Testpublic void selectById(){Account account = accountMapper.selectById(1);System.out.println(account);//Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}}@Testpublic void update(){Account account = new Account();account.setAid(5);account.setAname("wuhu");account.setApassword("123456");account.setAnickname("wuhuwuhu");accountMapper.update(account);}@Testpublic void insert(){Account account = new Account();account.setAname("aaa");account.setApassword("aaa");account.setAnickname("aaa");accountMapper.insert(account);}@Testpublic void delete(){accountMapper.delete(4);}
}

三.优化开发(日志别名配置文件)

mybatis-config.xml

1.配置properties

将数据库访问参数放在resources资源目录下的db.properties文件。

# 配置文件的key前面最好加上文件名
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql:///mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
db.username=root
db.password=123456

在MyBatis核心配置文件中通过properties标签引入。mybatis-config.xml

<!--加载并读取配置文件-->
<!--resource 从classes目录下寻找配置文件-->
<!--属性文件中的值 使用 ${key}-->
<properties resource="db.properties"> </properties>

获取

<!--环境-->
<environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${db.driver}"/><property name="url" value="${db.url}"/><property name="username" value="${db.username}"/><property name="password" value="${db.password}"/></dataSource></environment>
</environments>

核心配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><!--根节点configuration 配置-->
<configuration><!--加载并读取配置文件--><!--resource 从classes目录下寻找配置文件--><!--属性文件中的值 使用 ${key}--><properties resource="db.properties"> </properties><!--环境,很多环境,一个程序可能操作多个数据源(数据库),而且我们开发环境和本地测试环境也不一样--><!--对于不同数据库的操作我们理解为环境--><!--default就是程序默认使用的数据源--><!--环境--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${db.driver}"/><property name="url" value="${db.url}"/><property name="username" value="${db.username}"/><property name="password" value="${db.password}"/></dataSource></environment></environments><!--加密mapper的映射文件--><mappers><!--mapper文件的全路径,注意使用/分隔--><mapper resource="com/oracle/mapper/AccountMapper.xml"></mapper></mappers></configuration>

2.别名

别名,在mapper.xml文件中,有一个xml的属性 resultType,它表示select标签执行后的java数据类
型。

<select id="selectAll" resultType="com.oracle.model.Account">
select
aid,aname,apass,a_nikename as anikename
from
account
</select>

所谓别名映射,就是指 com.oracle.model.Account 类的全称可以简写

<!--model别名设置-->
<typeAliases>
<!--type是类型 alias是别名-->
<!--在mapper.xml中 <select id="selectAll" resultType="account"> -->
<!--typeAlias不足是需要一一配置-->
<!--<typeAlias type="com.oracle.model.Account" alias="account"/>-->
<!--能不能对整个model包进行别名设置-->
<!--包下所有的类的别名都是类的名字,且不区分大小写-->
<package name="com.oracle.model"/>
</typeAliases>
<!--别名-->
<typeAliases><!--单独一个类的别名映射--><!--<typeAlias type="org.westos.model.Account" alias="account"/>--><!--type是类型,alias是别名--><!--不足之处在于需要逐一配置--><!--对一个包下的所有类进行别名映射,别名都是类的名字,且不区分大小写--><package name="com.oracle.model"/></typeAliases>

3.映射文件mapper

在mybatis-config.xml中加载了mapper.xml。

如果mapper.xml很多,引入不方便,后期会采用Mapper代理。

 <!--加载mapper映射文件--><mappers><!--mapper文件的全路径,注意使用/分割--><mapper resource="com/oracle/mapper/AccountMapper.xml"/><!--package包扫描,加载的是接口 (mapper代理开发模式)--><!--<package name="com.oracle.model"/>--></mappers>

4. #{}和${}区分

#{}和${}都表示参数的替换,不同之处在于:

#{},占位符,会根据参数的类型,自动选择是否增加单引号,本质就是利用了PreparedStatement;

${}只是替换,也就是说,你传递String字符串,也是直接替换,不会为你自动增加单引号;

${ }只是替换,也就是说,你传递 String类型,也直接替换
#{ }使用的多 ; ${}模糊查询,最大的缺点sql注入【 ' or 1=1 -- 】

a. #{ }

#{ }使用的是OGNL 表达式获取对象中的数据

<insert id="insert" >insertintoaccount(aname,apassword,a_nikename)values(#{aname},#{apassword},#{anikename})
</insert>
public void insert(Account account) {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {sqlSession.insert("com.oracle.mapper.AccountMapper.insert", account);sqlSession.commit();}
}

以上两个代码结合,就是传递了Account对象,但是在sql运行的时候,获取到了对象的属性值,这种从
对象中获取属性值的方式,是通过OGNL对象图表达式语言完成的。

总结:#{}如果参数是非自定义对象,值可以随意填写;如果参数是自定义对象,那么值必须为属性。

#{}可以根据数据类型自动选择是否增加单引号。

5.${}

(1)

当参数是Integer时,#{aid}我们发现是能够获取值的

<select id="selectById" resultType="account">select aid, aname, apassword, a_nickname as anicknamefrom accountwhere aid = #{aid}
</select>

但是,${aid}会报错,

<select id="selectById" resultType="account">select aid, aname, apassword, a_nickname as anicknamefrom accountwhere aid = #{aid}
</select>
@Testpublic void selectById(){Account account = accountMapper.selectById(1);System.out.println(account);//Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}}

错误:

### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aid' in 'class java.lang.Integer'
### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aid' in 'class java.lang.Integer'

${ }对于int,Integer 数值类型,要求必须传递 value,一旦识别{value} ,一旦识别value,一旦识别{value}就直接替换,不使用OGNL

如果参数是对象类型,${ 对象的属性 },还是通过OGNL运算给数值

这里是把Integer当做了自定义对象,寻找属性aid了,然后就会报找不到错误。

将aid改为{aid}改为aid改为{value}。

 <select id="selectById" resultType="account">select aid, aname, apassword, a_nickname as anicknamefrom accountwhere aid = ${value}</select>

与之类似的还有String类型参数。

如果参数是String类型,${aname}的情况下,把String当做了自定义对象,寻找aname属性;

org.apache.ibatis.exceptions.PersistenceException:
### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aname' in 'class java.lang.String'
### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aname' in 'class java.lang.String'

${ }只是替换

org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.sql.SQLSyntaxErrorException: Unknown
column '李四' in 'field list'
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: insert into account(aname,apass,a_nikename)
values (李四,33,张三)
### Cause: java.sql.SQLSyntaxErrorException: Unknown column '李四' in 'field
list'

6.#{}

模糊查找使用#{}

如果参数是对象类型,${对象的属性},还是通过OGNL运算给数值。

但是,${对象的属性}只是替换,不会因为你是字符串就自动给你加上单引号。

ps:所以在传递对象作为参数时,选用#{}是最好的选择。

AccountMapper.xml

 <select id="selectByName" resultType="account">select aid, aname, apassword, a_nickname as anicknamefrom accountwhere aname like #{aname}</select>

AccountMapper.java

public List<Account> selectByName(String aname){SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();try {return sqlSession.selectList("com.oracle.mapper.AccountMapper.selectByName",aname);}finally {sqlSession.commit();sqlSession.close();}}

测试方法

  @Testpublic void selectByName(){List<Account> list = accountMapper.selectByName("%zhang%");System.out.println(list);}

如果使用#{},那么在参数中必须把%设置好了。

[Account{aid=1, aname='zhangsan', apassword='123456', anickname='张三'}]

使用${}带来的问题

<select id="selectByName2" resultType="account">select aid, aname, apassword, a_nickname  as  anicknamefrom accountwhere aname like '%${value}%'
</select>

AccountMapper.java

//模糊查询
public List<Account> selectByName(String name) {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {return sqlSession.selectList("com.oracle.mapper.AccountMapper.selectByName2", name);}
}

测试:

@Test
public void selectByName() {List<Account> list = accountMapper.selectByName("zhang");System.out.println(list);
}

结果:

[Account(aid=1, aname=zhangsan, apassword=nasgnahz, anickname=张三)]

但是,${}存在SQL注入的风险,慎用。

@Test
public void selectByName() {List<Account> list = accountMapper.selectByName("a' or 1 = 1 -- ");System.out.println(list);
}

最终的SQL为:

SELECT * FROM account WHERE aname LIKE '%a' OR 1 = 1 -- %';

1后面的--为SQL语言的注释。

查询结果为数据库中的所有数据:

[Account(aid=1, aname=zhangsan, apassword=nasgnahz, anickname=张三), Account(aid=2, aname=lisi, apassword=isil, anickname=李四)]

总结:${}如果参数是非自定义对象,那么值只能为value;如果参数是自定义对象,那么值必须为属性;

${}存在Sql注入的风险;

${}不会根据数据类型自动增加单引号。

7.得到插入数据的主键值

得到插入数据的主键值
比如说qq号,注册qq号,可能qq号是数据库的主键值。
在比如插入类别和商品,注意一次性插入,插入类别后返回主键值

<!--下面的insert语句中 #{} 中写的是对象的属性-->
<!--useGeneratedKeys 使用插入后的主键值-->
<!--keyProperty将主键值映射到哪一属性上--><!--主键自动获取前提是 数据库的主键生成方式 为 自动增长 mysql,sqlserver。oracle不是的--><!--oracle怎么办? oracle主键生成策略? sequence 序列--><!--mysql如何查询插入值得id,sql--><insert id="insert" useGeneratedKeys="true" keyProperty="aid" >insertintoaccount(aname,apass,a_nikename)values(#{aname},#{apass},#{anikename})</insert>

MyBatis支持插入数据并返回数据库中的主键值。

数据库的id值存在两种情况:

  • 数据库自动维护id的值

    • sqlserver
    • mysql
  • 另一种是序列sequence

    • oracle

      <!--像mysql、sqlserver,支持主键自动增长的数据库-->
      <!--useGeneratedKeys:使用插入后的主键值-->
      <!--keyProperty:将主键值映射到哪一属性上-->
      <insert id="insert" useGeneratedKeys="true" keyProperty="aid">insert into account(aname, apassword, a_nickname)values(#{aname}, #{apassword}, #{anickname})
      </insert>
@Test
public void insert() {Account account = new Account();account.setAname("wangwu");account.setApassword("uwgnaw");account.setAnickname("王五");accountMapper.insert(account);System.out.println(account.getAid());//3
}

last_insert_id()函数

<!--mysql还提供了一个函数last_insert_id(), 它必须紧跟插入语句,而且是插入语句先执行-->
<!--通过函数查询主键值,然后设置到属性中-->
<!--keyProperty:Java属性,order是指执行顺序在insert之前还是之后-->
<insert id="insert1"><selectKey keyProperty="aid" resultType="int" order="AFTER">select last_insert_id()</selectKey>insert into account(aname, apassword, a_nickname)values(#{aname}, #{apassword}, #{anickname})
</insert>
@Test
public void insert() {//2、插入一条记录Account account = new Account();account.setAname("john");account.setApassword("123456");account.setAnickname("jj");accountMapper.insert(account);System.out.println(account.getAid());//4
}

service层的作业+mybatis中的重要组件相关推荐

  1. Java Web学习总结(30)——Service层在MVC框架中的意义和职责

    mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层设计, ...

  2. SpringBoot在自定义类中调用service层等Spring其他层

    解决方案: 1.上代码@Component public class ServerHandler extends IoHandlerAdapter {@Autowiredprotected Healt ...

  3. Springboot三层架构--DAO层、Service层、Colltroler层--这波我在外太空

    目录 1.DAO层 Dao层的设计 2.Service层 Service层的设计 设计Service层的优点 Dao与Service的关系 3.Colltroler层 Collertroler层的设计 ...

  4. service层的作用

    一直不太明白service层的作用,有时候甚至感觉service层可有可无. dao层中已经有操作数据库的方法了,为什么还要service层去封装?有什么好处? 首先是mvc三层架构 mvc三层架构 ...

  5. 3、JavaWeb中Service层的作用、MyBatis的重要组件、mybatis-config.xml中的别名映射、properties配置、#{}和${}的区别、获取插入数据的主键值

    文章目录 1.Service层的作用 2.MyBatis重要组件 Resources SqlSessionFactoryBuilder SqlSessionFactory SqlSession 针对上 ...

  6. SpringBoot框架中的DAO(mapper)层、Entity层、Service层、Controller层

    Entity层:实体层 数据库在项目中的类 Entity层是实体层,也就是所谓的model,也称为pojo层,是数据库在项目中的类,该文件包含实体类的属性和对应属性的set.get方法: DAO层: ...

  7. 解析Java框架中entity层,mapper层,service层,controller各层作用

    一.entity层 别名: model层 ,domain层 用途: 实体层,用于存放我们的实体类,与数据库中的属性值基本保持一致,实现set和get的方法. 例子:user表的实体User publi ...

  8. Spring、Mybatis整合Service优化思路,DAO层、Service层最终编码以及log4j日志的使用

    5. Spring.Mybatis整合Service层事务控制优化思路分析 # spring中处理事务的两种方式1. 编程式事务处理定义:通过在业务层中注入事务管理器对象,然后通过编码的方式进行事务控 ...

  9. Spring整合Mybatis之DAO层、Service层开发

    3. Spring整合Mybatis编程DAO层开发 1. 项目引入相关依赖spring mybatis mysql mybatis-spring druid2. 编写spring.xml整合:spr ...

最新文章

  1. 学好python工资一般多少钱-Python工资一般是多少 看完吓你一跳
  2. excel插入一列日期 pandas_将日期和时间从Excel拉到Pandas并将其组合为时间戳
  3. JavaScript中的匿名函数及函数的闭包
  4. 往sde中导入要素类报错000732
  5. splitpane如何设置竖条的宽度_页面中有间隔的方格布局如何完美实现?
  6. MySQL中my.cnf解析
  7. 《美团数据平台及数仓建设实践》(209页).PDF
  8. 回溯法——批处理作业调度
  9. 数值补码和原码计算方法介绍
  10. 关于动态规划的一点学习感想
  11. 显示器不亮电源灯闪_台式电脑显示屏不亮指示灯一直闪烁
  12. 【系统集成项目管理工程师】考点:挣值管理 (附计算公式及思维导图)
  13. 游戏开发中的物理之软体
  14. Windows Azure Virtual Network (13) 跨数据中心之间的虚拟网络点对点连接VNet Peering
  15. 量化投资学习必读书目(八)——《短线交易大师》
  16. 设计师如何提高个人的色彩搭配能力?
  17. 数字化转型思考的延伸问题
  18. 通俗理解java的可见性、有序性和原子性
  19. 好玩的CMD几个命令
  20. lock与unlock用法(简单易懂)

热门文章

  1. Netty游戏服务器实战开发(6):Netty整合Zookeeper实现分布式服务发现与注册
  2. 图书借阅管理系统实现
  3. 原型法和面向对象的分析与设计方法
  4. 哈工大软件过程与工具复习1——第1-2讲 概论与核心思想
  5. 【漏洞复现】MS17-010漏洞(永恒之蓝)复现
  6. AI选择描边比例缩放钢笔文字形状线段、弧形渐变混合工具使用
  7. 清明节网站变灰是如何实现的
  8. 剑网3指尖江湖开局门派选TA最好 叉叉助手伴你快意江湖
  9. 计算机网络脆弱性评估方法研究
  10. “流支付”掀起互联网支付创新浪潮,SAK支付白皮书揭秘