问题遇到的现象和发生背景
在编写一个面向切面的简单程序时尝试使用Mybatis, 但是卡在org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
错误中无法解决.
问题相关代码,请勿粘贴截图
Mapper类:
@Mapper
@Repository
public interface UserLogMapper {
int insertLogin(@Param("userLog") UserLog userLog); // 登入记录
}
Service类:
@Service
public class UserLogService {
@Autowired
UserLogMapper userLogMapper;
/**
* 插入登入记录
* @param user 用户体
* @return 插入反馈
*/
public int insertLogin(User user){
Timestamp time = new Timestamp(System.currentTimeMillis());
UserLog userLog = new UserLog(user.getId(), user.getUsername(), time, true);
return userLogMapper.insertLogin(userLog);
}
}
<!-UserLogMapper.xml-!>
<?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">
<mapper namespace="xmu.mw.aoptest.Mapper.UserLogMapper">
<resultMap id="BaseResultMap" type="xmu.mw.aoptest.Model.UserLog">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="time" jdbcType="TIMESTAMP" property="time" />
<result column="type" jdbcType="BOOLEAN" property="type" />
</resultMap>
<sql id="Base_Column_List">
id, username, `time`, `type`
</sql>
<insert id="insertLogin"></insert>
</mapper>
/**
* 测试类
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class LogAOPTest {
// 直接用Mapper避免多层调用导致StackOverflow
@Autowired
private UserLogMapper userLogMapper;
/**
* 测试登入记录
*/
@Test
public void insertLoginTest(){
User user = new User(1,"usr50035", "123456");
Timestamp time = new Timestamp(System.currentTimeMillis());
UserLog userLog = new UserLog(user.getId(), user.getUsername(), time, true);
int status = userLogMapper.insertLogin(userLog);
System.out.println(status);
}
}
AOP类:
@Aspect
@Component
public class LogAOP {
@Autowired
private UserLogService userLogService;
// 登入切点
@Around("execution(* xmu.mw.aoptest.Service.UserLogService.insertLogin(*))")
public void loginLog(ProceedingJoinPoint joinPoint) throws Throwable{
User user = new User();
try{
Object o = joinPoint.proceed();
user = (User)o;
}
finally{
userLogService.insertLogin(user);
}
}
}
Model: User类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserLog implements Serializable {
private Integer id; // 唯一标识符
private String username; // 用户名
private Timestamp time; // 登录/出时间
private Boolean type; // 登录登出类型 true:login, false:logout
private static final long serialVersionUID = 1L;
}
运行结果及报错内容
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): xmu.mw.aoptest.Mapper.UserLogMapper.insertLogin
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235)
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53)
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:108)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at org.apache.ibatis.util.MapUtil.computeIfAbsent(MapUtil.java:36)
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:95)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at com.sun.proxy.$Proxy66.insertLogin(Unknown Source)
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:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy67.insertLogin(Unknown Source)
at xmu.mw.aoptest.LogAOPTest.insertLoginTest(LogAOPTest.java:35)
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:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
我的解答思路和尝试过的方法
尝试过检查xml文件的namespace, 通过插件也可以正常转到目标代码, 也加入了@MapperScan注解, 该有的@Service之类的注解也有.
不知道如何解决问题.
我想要达到的结果
构建一个用户记录的切面.
对于所有的"登录"操作, 记录各各次登录的时间、用户,存入UserLog表格中.
可以通过测试, 结果是正常向数据库中插入一条登录的信息, 包括id, username, timestamp, type
.