Play 1.x 프레임워크 학습 7: 다중 데이터베이스 전환 및 소스 수정(Databases Switch And Modify Source Code)
jpa.dialect=org.hibernate.dialect.MySQLDialect
db.url=jdbc:mysql://basedbip:3306/pop?autoReconnect=true&useUnicode=true&characterEncoding=utf-8
db.driver=com.mysql.jdbc.Driver
db.user=root
db.pass=root
db=pop
db_01.url=jdbc:mysql://anotherdbip:3306/pop?autoReconnect=true&useUnicode=true&characterEncoding=utf-8
db_01.driver=com.mysql.jdbc.Driver
db_01.user=root
db_01.pass=root
db_01=pop01
라이브러리를 자르는 방법은 다음과 같습니다. Util/DB.java
package util;
import play.db.jpa.JPA;
public class DB {
public static void changeDB(String dbconfigname, String dbname){
try {
JPA.setCurrentConfigName(dbconfigname);
if (JPA.em().getTransaction().isActive() == false) {
JPA.em().getTransaction().begin();
}
JPA.em().createNativeQuery("use "+dbname).executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
}
상술한 설정을 완성하면 라이브러리를 자유롭게 절단할 수 있지만, 실제 실행 중이라면 중대한 문제가 발생할 수 있습니다.컨트롤러 층에서 데이터 봉인과 관련된 것입니다. 예를 들어 사용자 수정:
public static void update(@Required @Valid User user){
user.save();
renderText(user.id);
}
user 대상 파라미터를 봉인할 때play1.x 프레임워크의 자동 조회 데이터베이스입니다. 이 처리는 컨트롤러 방법 이전이기 때문에 라이브러리를 절단할 수 없습니다!메인 라이브러리와 라이브러리 테이블과 데이터가 다르기 때문에 오류가 발생합니다!
play.exceptions.UnexpectedException: Unexpected Error
at play.data.validation.ValidationPlugin.beforeActionInvocation(ValidationPlugin.java:59)
at play.plugins.PluginCollection.beforeActionInvocation(PluginCollection.java:518)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:131)
at Invocation.HTTP Request(Play!)
Caused by: play.exceptions.UnexpectedException: Unexpected Error
at play.db.jpa.JPAPlugin.bind(JPAPlugin.java:67)
at play.plugins.PluginCollection.bind(PluginCollection.java:468)
at play.data.binding.Binder.bind(Binder.java:309)
at play.mvc.ActionInvoker.getActionMethodArgs(ActionInvoker.java:621)
at play.data.validation.ValidationPlugin$Validator.validateAction(ValidationPlugin.java:95)
at play.data.validation.ValidationPlugin.beforeActionInvocation(ValidationPlugin.java:51)
... 3 more
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1214)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:307)
at play.db.jpa.JPAPlugin.bind(JPAPlugin.java:62)
... 8 more
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2536)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:274)
... 9 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table ´pop.user´ doesn´t exist
at com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
at com.mysql.jdbc.Util.getInstance(Util.java:382)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3593)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3525)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1986)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2140)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2626)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2111)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2273)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:802)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2533)
... 17 more
오류 창고의 마지막 메시지를 보았습니다. 시계가 존재하지 않습니다!부모 컨트롤러 컨트롤러에서 @before 탭을 이용하여 방법이 호출되기 전에 차단 설정을 통일하고 싶을 수도 있습니다.하지만 결과는 너를 실망시킬 거야!잘못은 여전할 거야!이때 우리는 오류 정보에 근거하여play 프레임워크의 원본 코드를 깊이 있게 해야 한다.caused by에서 JPA Plugin이 보입니다.java, 그런데 이미 JPA 조회 데이터베이스에 썼어요.두 번째 caused by 에서 JPA Plugin.java: 62곳에서 jpaplugin을 볼 수 있는 bind 방법은 다음과 같습니다.
@Override
@SuppressWarnings("unchecked")
public Object bind(String name, Class clazz, java.lang.reflect.Type type, Annotation[] annotations, Map params) {
// TODO need to be more generic in order to work with JPASupport
if (JPABase.class.isAssignableFrom(clazz)) {
String keyName = Model.Manager.factoryFor(clazz).keyName();
String idKey = name + "." + keyName;
if (params.containsKey(idKey) && params.get(idKey).length > 0 && params.get(idKey)[0] != null && params.get(idKey)[0].trim().length() > 0) {
String id = params.get(idKey)[0];
try {
Query query = JPA.em().createQuery("from " + clazz.getName() + " o where o." + keyName + " = ?");
query.setParameter(1, play.data.binding.Binder.directBind(name, annotations, id + "", Model.Manager.factoryFor(clazz).keyType()));
Object o = query.getSingleResult();
return GenericModel.edit(o, name, params, annotations);
} catch (NoResultException e) {
// ok
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
return GenericModel.create(clazz, name, params, annotations);
}
return super.bind(name, clazz, type, annotations, params);
}
일목요연하다
Query query = JPA.em().createQuery("from " + clazz.getName() + " o where o." + keyName + " = ?");
메인 키에 따라 데이터 테이블에 데이터를 조회하지만 이때 해당하는 라이브러리를 자르지 않았기 때문에 조회표가 없습니다!(메인 라이브러리에 해당하는 표가 있어도 해당하는 데이터가 없다.)왜 창고를 자르지 않았다고 해요?@before로 처리했잖아요.ActionInvoker에 대한 잘못된 정보를 계속 찾습니다.java의 invoke 방법, 코드가 너무 많아서 잘못된 알림만 붙인 131행 부근
ControllerInstrumentation.stopActionCall();
Play.pluginCollection.beforeActionInvocation(actionMethod);
// Monitoring
monitor = MonitorFactory.start(request.action + "()");
// 3. Invoke the action
try {
// @Before
handleBefores(request);
// Action
Result actionResult = null;
String cacheKey = null;
여기 있습니다.
Play.pluginCollection.beforeActionInvocation(actionMethod);
play 프레임워크는 일련의 플러그인 호출 전 준비 작업을 처리합니다. redisplugin/jpaplugin/validationplugin/wsplugin 등입니다. 그 중에서 validationplugin은 모든 검증 주석이 있는 실체 클래스를 처리하는 동시에 @id 주석의 메인 키를 눌러서 @before를 처리하는 방법도 포함합니다.
handleBefores(request);
그러니까 befores를 써도 소용없어!이 실행 가능한 방안은play 원본 코드를 수정하고befores 주석을 본떠서 처리하는 것입니다.mvc에서 BeforeValidation 메모를 추가하여 검증하기 전에 라이브러리를 잘라냅니다!
play.mvc.BeforeValidation.java
package play.mvc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mark this method as @BeforeValidation interceptor
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeValidation {
/**
* Does not intercept these actions
*/
String[] unless() default {};
String[] only() default {};
/**
* Interceptor priority (0 is high priority)
*/
int priority() default 0;
}
동시에 ActionInvoker에 메서드 handleBeforeValidations 재생을 추가합니다.mvc.ActionInvoker.java
private static void handleBefores(Http.Request request) throws Exception {
List befores = Java.findAllAnnotatedMethods(Controller.getControllerClass(), Before.class);
Collections.sort(befores, new Comparator() {
public int compare(Method m1, Method m2) {
Before before1 = m1.getAnnotation(Before.class);
Before before2 = m2.getAnnotation(Before.class);
return before1.priority() - before2.priority();
}
});
ControllerInstrumentation.stopActionCall();
for (Method before : befores) {
String[] unless = before.getAnnotation(Before.class).unless();
String[] only = before.getAnnotation(Before.class).only();
boolean skip = false;
for (String un : only) {
if (!un.contains(".")) {
un = before.getDeclaringClass().getName().substring(12).replace("$", "") + "." + un;
}
if (un.equals(request.action)) {
skip = false;
break;
} else {
skip = true;
}
}
for (String un : unless) {
if (!un.contains(".")) {
un = before.getDeclaringClass().getName().substring(12).replace("$", "") + "." + un;
}
if (un.equals(request.action)) {
skip = true;
break;
}
}
if (!skip) {
before.setAccessible(true);
inferResult(invokeControllerMethod(before));
}
}
}
HandleBeforeValidations 처리 방법을 Play에 추가합니다.pluginCollection.before Action Invocation 앞.
ControllerInstrumentation.stopActionCall();
//@BeforeValidation
handleBeforeValidations(request);
Play.pluginCollection.beforeActionInvocation(actionMethod);
// Monitoring
monitor = MonitorFactory.start(request.action + "()");
// 3. Invoke the action
try {
// @Before
handleBefores(request);
// Action
Result actionResult = null;
String cacheKey = null;
이렇게 하면 BeforeValidation 주석을 통해 응용 프로그램에 해당하는 라이브러리 논리를 추가할 수 있다.Jpa 봉인 대상 매개 변수의 오류 문제를 해결할 수 있습니다.또한 라이브러리 커팅 근거는 상응하는 데이터 원본 등 데이터를 하나의 대상에 저장하고sessionid로 키를 만들어redis에 저장할 수 있으며 요청할 때마다 라이브러리 커팅을 하고 로그인 여부를 검사할 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
SQLite의 query로 망설임이것은 내가 처음 안드로이드 응용 프로그램 개발에서 망설이고, 그 후 해결 된 방법을 비망록으로 철자하고 있습니다. java에서 SQLite를 이용한 애플리케이션을 작성하는 동안 EditText에 입력된 item이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.