- 在上一篇文章中,练习了mybatis入门案例,过程中疏忽了一个步骤,就是日志文件的导入,我这里文件名叫做log4j.properties,位置在resources包下,其内容网上有很多格式,我这里使用其一种,如下:
# priority :debug<info<warn<error
#you cannot specify every priority with different file for log4j
log4j.rootLogger=debug,stdout,info,debug,warn,error
#console
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 a}]:%p %l%m%n
#info log
log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.info.File=./src/com/hp/log/info.log
log4j.appender.info.Append=true
log4j.appender.info.Threshold=INFO
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#debug log
log4j.logger.debug=debug
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.debug.File=./src/com/hp/log/debug.log
log4j.appender.debug.Append=true
log4j.appender.debug.Threshold=DEBUG
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#warn log
log4j.logger.warn=warn
log4j.appender.warn=org.apache.log4j.DailyRollingFileAppender
log4j.appender.warn.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.warn.File=./src/com/hp/log/warn.log
log4j.appender.warn.Append=true
log4j.appender.warn.Threshold=WARN
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#error
log4j.logger.error=error
log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.error.File = ./src/com/hp/log/error.log
log4j.appender.error.Append = true
log4j.appender.error.Threshold = ERROR
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
这段代码没有任何技术含量,在这里就不用自己敲了,复制粘贴即可
最后,整个文件的目录结构如下:(QueryVO文件可忽略不计,后面会提到)
我在dao包下,还写了IUerDaoImpl类,此类继承IUserDao接口,是另一种写法,这里不予叙述,后面就不会再写这个类了。
最后,对整个入门案例进行一下回顾,看一下整个流程
从这里开始今天的内容
今天在之前的基础上,新增 添加用户,修改用户,删除用户等功能
1.实现添加用户,修改用户,删除用户的功能
在IUserDao接口下,添加这几个方法,方法名最好见名知意。
public interface IUserDao {
//查询用户
List<User> findAll();
//添加用户
void addUser(User user);
//修改用户
void update(User user);//修改的用户是user中的id,修改的内容是user中的其余内容
//删除用户
void delete(int id);
}
然后在IUserDao.xml配置文件中写具体的sql语句,插一句,后面sql语句主要在mapper标签中写,查找在select标签中写,修改在update标签中写,删除在update标签中写,用的最多的也是这几个标签。最后写好的代码如下:
<?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="dao.IUserDao">
<!-- 注:id的值是接口中的方法名 resultType:查询返回的结果类型-->
<select id="findAll" resultType="user">
select * from user;
</select>
<update id="addUser" parameterType="domain.User">
insert into user (username,password,sex,address) values (#{username},#{password},#{sex},#{address});
</update>
<update id="update" parameterType="domain.User">
update user set username=#{username},password=#{password},sex=#{sex},address=#{address} where id=#{id};
</update>
<delete id="delete" parameterType="int">
delete from user where id=#{id};
</delete>
</mapper>
这里对几个属性进行说明:
- resultType="user"输出结果类型是user类型,这里user的完整格式是domain.User,因为我在配置了别名,所以这里直接写user
- parameterType=“domain.User” 输入参数类型是user类型。
- 如果输入参数类型是int或其他基本类型时,parameter可以不写,写上也没有错,但如果是实体类类型,建议写上。要是输入类型和输出类型都是user类型,那么resultType和parameterType均要写上。
最后,就是写测试文件了
简单说明一下,在修改方法中,我定义了user对象,其set的id就是要修改用户的id号,其余信息是想要改的信息。其余两个测试功能简单,不做补充。测试文件如下:
public class MyTest {
//不需要实体类完成增删改查的功能
private InputStream in;
private SqlSession sqlSession;
IUserDao dao;
@Before
public void before(){
try {
//读取mybatis核心配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
//构建工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//打开SqlSession
sqlSession = factory.openSession();
//获取接口的代理对象
dao = sqlSession.getMapper(IUserDao.class);
}
@After
public void after(){
// 释放资源
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
sqlSession.close();
}
@Test
public void testAddUser() throws IOException {
//创建一个用户
User user = new User();
user.setUsername("吕布");
user.setPassword("666333");
user.setSex("男");
user.setAddress("徐州");
dao.addUser(user);
sqlSession.commit();
}
@Test
public void testUpdate(){
//创建一个用户,确定修改后的参数
User user = new User();
user.setId(26);
user.setUsername("吕小布");
user.setPassword("666333");
user.setSex("男");
user.setAddress("徐州");
dao.update(user);
sqlSession.commit();
}
}
其余方法与之类似。
2.考虑一下这个情况,在实体类的属性名和表中的字段名不一致时,我们再用上面的代码查,结果会得到null。虽然这样有点自己为难自己,但有时确实有这种需求,这里介绍一个新的标签,让我们在实体类的属性名和表中的字段名不一致时,也能正常实现其功能。
首先,先改一下之前实体类中的属性名,我这里在之前都加上了user_,如下
public class User2 {
private long user_id;
private String user_username;
private String user_password;
private String user_sex;
private String user_address;
其get,set,toString方法省略。
然后,我们需要在IUserDao.xml配置文件中,mapper标签下新建一个resultMap标签,配置各个属性名和表中名的对应关系。如下
<mapper namespace="dao.IUserDao">
<resultMap id="myMap" type="domain.User2">
<!--配置实体类和表中主键的对应关系-->
<id property="user_id" column="id"></id>
<!--配置其他普通字段的对应关系-->
<result property="user_username" column="username"></result>
<result property="user_password" column="password"></result>
<result property="user_sex" column="sex"></result>
<result property="user_address" column="address"></result>
</resultMap>
然后在下面写sql语句,这里我们需要加上一个属性,resultMap=“myMap”,引用我们上面的映射配置。如下:
<select id="findById" resultType="domain.User2" resultMap="myMap" parameterType="int">
select * from user where id=#{user_id};
</select>
这里就用一个按照id查找用户为例,其余功能就不展示了,有兴趣的伙伴可以练习一下其他功能,毕竟看的再多,没有自己动手敲一遍来的踏实。
测试文件和之前的差不多,这里就不再赘述了。
3.给实体类起别名
如上面所说,我在一些地方,如parameterType这里时,直接写的user,这是因为我给User这个类起了别名,所以在用的时候,不用写具体路径,直接写我起的别名就好。
这个配置文件在SqlMapConfig.xml中写,使用的是typeAliases标签。如下:
<configuration>
<typeAliases>
<!-- 给实体类起别名,这样后面就不用写User具体路径了,只写user就行-->
<typeAlias type="domain.User" alias="user"></typeAlias>
</typeAliases>
想给哪个类起别名,我们就可以一个一个写,这里可以写多个。但如果觉得这样还是麻烦,我们可以用package标签,给该包下的所有实体类配置别名,具体实现如下:
<typeAliases>
<!-- 如果觉得一个类一个类起别名麻烦,我们可以给某个包下所有实体类起别名,如下-->
<package name="domain"></package>
<!-- 上行代码为domain包下的所有实体类起别名,此别名可以是类名本名,或类名全大写,或类名全小写。这三个用哪个都可以-->
</typeAliases>
我们给某个包下所有的实体类配置了别名,这个别名叫啥,可以是原来的类名可以是原来的类名全部小写,或全部大写例如:User或user或USER这三个都是别名用哪个都行。
4.将配置文件单独写。
为了解耦,我们可以把配置文件单独写出来
在resources包下,新建一个文件,起名jdbcConfig.properties,在里面写下面代码:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456
然后在SqlConfig.xml配置文件中进行配置,导入配置文件
首先,写一个properties标签,导入文件,需要注意的是,properties标签在configuration标签里面的最前面,在typeAliases前面,如下
<configuration>
<!-- 引入外部配置文件,此标签写在configuration最前面-->
<properties resource="jdbcConfig.properties"/>
<typeAliases>
然后,将之前配置的参数进行修改即可,如下:
<dataSource type="POOLED">
<!-- 配置最常用的四个参数-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
自此以后,我们要是想换其他数据库,直接在jdbc.properties中修改就好了
5.使用package自动扫描
在SqlMapConfig.xml配置文件中的最后,mapper里我们可以使用package标签,自动扫描该包下的所有接口,这样就不用手动添加了,如下:
<mappers>
<!-- 可以用package标签,对包下的所有接口进行扫描-->
<package name="dao"/>
</mappers>