数据库中需要定义一个表,java定义一个model。
定义对应接口增删改查
@Mapper
public interface UserMapper {
List<User> getUserById(int id);
boolean addUser(User user);
boolean delUser(int id);
boolean updateName(User user);
}
定义映射文件User.xml
每个mapper标签中namespace属性代表这个xml文件映射的接口。
每个子标签中有2个属性:
<mapper namespace="mapper.UserMapper" >
<select id="getUserById" resultType="model.User">
select * from user where user_id = #{id};
select>
<insert id="addUser" parameterType="model.User">
insert into user(name,password) values (#{name},#{password});
insert>
<delete id="delUser">
delete from user WHERE user_id=#{id};
delete>
<update id="updateName">
update user SET name=#{name} where user_id=#{userId};
update>
mapper>
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void before(){
try{
String resource = "generatorConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void selectTest() {
SqlSession openSession=sqlSessionFactory.openSession();
UserMapper userMapper=openSession.getMapper(UserMapper.class);
List<User> user=userMapper.getUserById(2);
System.out.println(user);
assertTrue(user.size()!=0);
}
@Test
public void addTest() {
SqlSession openSession=sqlSessionFactory.openSession();
UserMapper userMapper=openSession.getMapper(UserMapper.class);
boolean result=userMapper.addUser(new User("小明","123123"));
openSession.commit();
assertTrue(result);
}
@Test
public void delTest() {
SqlSession openSession=sqlSessionFactory.openSession();
UserMapper userMapper=openSession.getMapper(UserMapper.class);
boolean result=userMapper.delUser(2);
openSession.commit();
assertTrue(result);
}
@Test
public void updateTest() {
SqlSession openSession=sqlSessionFactory.openSession();
UserMapper userMapper=openSession.getMapper(UserMapper.class);
boolean result=userMapper.updateName(new User(3,"123123"));
openSession.commit();
assertTrue(result);
}
}
注意:
User user=new User("小明","123123")
boolean result=userMapper.addUser(user);
System.out.printlin(user.getId())
此时打印出的结果就是user的id。
public class UserMapper {
List<User> getUserById(int id);
}
<select id="getUserById" resultType="model.User">
select * from user where user_id = #{asasaid};
select>
这里#{}中不管写什么都是可以识别的。
public class UserMapper {
List<User> getUserById(int id,String name);
}
<select id="getUserById" resultType="model.User">
select * from user where user_id = #{id} and name = #{name}
select>
这里就会报异常。
那么怎么解决呢,只要假如@Param()注解就ok了。
public class UserMapper {
List<User> getUser(@Param("id")int id,
@Param("name")String name);
}
public class UserMapper {
List<User> getUser(User user);
}
user中写好id值和name的值。
public class UserMapper {
List<User> getUser(Map<String,Object> map );
}
public void updateTest() {
SqlSession openSession=sqlSessionFactory.openSession();
UserMapper userMapper=openSession.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<>()
map.put("id",1)
map.put("name","tom")
boolean result=userMapper.getUser(map);
openSession.commit();
assertTrue(result);
}
什么是预编译:预编译就是将sql变成一个函数,函数的变量用占位符表示,后面注入的参数系统就会默认它仅仅是一个参数,而不会认为是一个sql语句,不会再次编译,这样就可以防止sql注入。
一般情况下使用#{},在原生jdbc不支持占位符情况下用${},比如表名的拼接就需要使用${}。
比如#{email,javaType=String,jdbcType=varchar(30)}
接口Java代码如下;
@MapKey("id")
Map<Integer,User> getUser(int id);
@MapKey指定了Map的键对应的是表中的哪个字段。
<map resource="mapper.UserMapper">
<resultMap type="model.User" id="user">
<id column="id" property="id"/>
<result colume="name" property="name"/>
resultMap>
<select id="getUser" resultMap="user">
select * from user
select>
map>
id标签指的是主键,result标签指的是普通列。
column代表表中列名,property代表javaBean中的对应命名。
比如这时候User中存在Department类,如何查询呢
public class User {
private int userId;
private String name;
private String password;
private Department department;
}
public class Department {
private int depId;
private String depName;
}
<map resource="mapper.UserMapper">
<resultMap type="model.User" id="user">
<id column="user_id" property="userId"/>
<result colume="name" property="name"/>
<result colume="password" property="password"/>
<result colume="dep_id" property="department.depId"/>
<result colume="dep_name " property="department.depName"/>
resultMap>
<select id="getUser" resultMap="user">
select user_id,name,password,dep_id,dep_name from user natrual join department.
select>
map>
<map resource="mapper.UserMapper">
<resultMap type="model.User" id="user">
<id column="user_id" property="userId"/>
<result colume="name" property="name"/>
<result colume="password" property="password"/>
<association property="department" javaType="model.Department">
<id colume="dep_id" property="depId"/>
<result colume="dep_name " property="depName"/>
association>
resultMap>
<select id="getUser" resultMap="user">
select user_id,name,password,dep_id,dep_name from user natrual join department.
select>
map>
此时DeptMapper中就需要getDeptById(int id)接口。
<resultMap id="MyEmpByStep" type="com.yuehailin.entity.Employee">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<association property="dept"
select="com.yuehailin.dao.DepartmentMapper.getDeptById"
column="d_id">
association>
resultMap>
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
SELECT * FROM tbl_employee WHERE id=#{id}
select>
column属性可以使用{key=value,key2=value}来应对多个属性的值。
在分布查询时,如果只是用到user中的熟悉,如果同时加载department的话会增加内存,只有在用到的时候再加载就叫延迟加载。
Mybatis配置文件中通过两个属性lazyLoadingEnabled和aggressiveLazyLoading来控制延迟加载和按需加载。
在generatorConfig.xml中添加
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="true"/>
settings>
假如有以下场景
public class Type {
private int typeId;
private String typeName;
private List<User> userList;
public int getTypeId() {
return typeId;
}
public void setTypeId(int typeId) {
this.typeId = typeId;
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String name) {
this.typeName = name;
}
@Override
public String toString() {
return "Type{" +
"typeId=" + typeId +
", typeName='" + typeName + '\'' +
", userList=" + userList +
'}';
}
}
此时一个type对应多个user如何是好,那么就需要在xml中定义
<resultMap id="getTypeByIdAndUsers" type="model.Type">
<id column="type_id" property="typeId"/>
<result column="type_name" property="typeName"/>
<collection property="userList" ofType="model.User">
<id column="user_id" property="userId"/>
<result column="name" property="name"/>
<result column="password" property="password"/>
collection>
resultMap>
<select id="getTypeByIdAndUsers" resultMap="getTypeByIdAndUsers">
select * from user natural join type where type_id = #{type_id};
select>